#####################################################################
# The cmake/Check{C,CXX}CompilerFlag.cmake files in the GROMACS distribution
-# are used with permission from CMake v2.8.9 so that GROMACS can detect
-# invalid options with the Intel Compilers.
+# are used with permission from CMake v3.0.0 so that GROMACS can detect
+# invalid options with the Intel Compilers, and we have added a line
+# to detect warnings with the Fujitsu compilers on K computer.
+# CMake-3.0 also has a bug where the FAIL_REGEX pattern for AIX contains
+# a semicolon. Since this is also used as a separator in lists inside CMake,
+# that string ends up being split into two separate patterns, and the last
+# part is just a single word that also matches other messages. We solved this
+# by replacing the semicolon with a period that matches any character.
+#
# These files should be removed from the source tree when a CMake version that
# includes the features in question becomes required for building GROMACS.
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
-
include(gmxCFlags)
gmx_c_flags()
check_function_exists(_commit HAVE__COMMIT)
check_function_exists(sigaction HAVE_SIGACTION)
check_function_exists(sysconf HAVE_SYSCONF)
-check_function_exists(sched_setaffinity HAVE_SCHED_SETAFFINITY)
-check_function_exists(sched_getaffinity HAVE_SCHED_GETAFFINITY)
check_function_exists(rsqrt HAVE_RSQRT)
check_function_exists(rsqrtf HAVE_RSQRTF)
check_function_exists(sqrtf HAVE_SQRTF)
check_library_exists(m sqrt "" HAVE_LIBM)
check_library_exists(rt clock_gettime "" HAVE_CLOCK_GETTIME)
+include(TestSchedAffinity)
+test_sched_affinity(HAVE_SCHED_AFFINITY)
+
include(TestBigEndian)
test_big_endian(GMX_INTEGER_BIG_ENDIAN)
FAIL_REGEX "[Uu]nknown option" # HP
FAIL_REGEX "[Ww]arning: [Oo]ption" # SunPro
FAIL_REGEX "command option .* is not recognized" # XL
+ FAIL_REGEX "command option .* contains an incorrect subargument" # XL
+ FAIL_REGEX "not supported in this configuration. ignored" # AIX
+ FAIL_REGEX "File with unknown suffix passed to linker" # PGI
FAIL_REGEX "WARNING: unknown flag:" # Open64
+ FAIL_REGEX "Incorrect command line option:" # Borland
+ FAIL_REGEX "Warning: illegal option" # SunStudio 12
+ FAIL_REGEX "[Ww]arning: Invalid" # Fujitsu
)
SET (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
ENDMACRO (CHECK_C_COMPILER_FLAG)
FAIL_REGEX "[Uu]nknown option" # HP
FAIL_REGEX "[Ww]arning: [Oo]ption" # SunPro
FAIL_REGEX "command option .* is not recognized" # XL
- FAIL_REGEX "not supported in this configuration. ignored" # AIX
+ FAIL_REGEX "command option .* contains an incorrect subargument" # XL
+ FAIL_REGEX "not supported in this configuration. ignored" # AIX
FAIL_REGEX "File with unknown suffix passed to linker" # PGI
FAIL_REGEX "WARNING: unknown flag:" # Open64
+ FAIL_REGEX "Incorrect command line option:" # Borland
+ FAIL_REGEX "Warning: illegal option" # SunStudio 12
+ FAIL_REGEX "[Ww]arning: Invalid" # Fujitsu
)
SET (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
ENDMACRO (CHECK_CXX_COMPILER_FLAG)
unsigned int _eax,_ebx,_ecx,_edx;
unsigned int level = 0;
- /* Test gcc inline asm for x86 */
-#if defined (__LP64__) || defined (_M_X64)
+ /* Test gcc inline asm for x86. Note that we CANNOT plainly use __x86_64__
+ * to correspond to a 64-bit environment without also checking that __ILP32__
+ * is NOT set, since x32 uses __x86_64__.
+ */
+#if (defined(__x86_64__) && !defined(__ILP32__))
__asm__("push %%rbx \n\t"
"cpuid \n\t"
"movl %%ebx, %1 \n\t"
"pop %%rbx \n\t"
: "=a"(_eax), "=r"(_ebx), "=c"(_ecx), "=d"(_edx) : "0"(level));
-#else
+#elif (defined(__x86_64__) && defined(__ILP32__)) || defined(__i386__)
__asm__("push %%ebx \n\t"
"cpuid \n\t"
"movl %%ebx, %1 \n\t"
"pop %%ebx \n\t"
: "=a"(_eax), "=r"(_ebx), "=c"(_ecx), "=d"(_edx) : "0"(level));
+#else
+# error Cannot detect whether this is a 32-bit or 64-bit x86 build.
#endif
return 0;
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014, by the GROMACS development team, led by
+# Copyright (c) 2012,2014, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# To help us fund GROMACS development, we humbly ask that you cite
# the research papers on the package. Check out http://www.gromacs.org.
-# GMock uses tuples extensively, and MSVC bundles a tuple library that
-# is not compatible with the standard. r675 of googletest works around
-# this properly, but that's not in GMock 1.7.0. That logic is
-# duplicated here. See
-# https://code.google.com/p/googletest/source/detail?r=675#, but note
-# that its summary does not represent its code correctly.
-#
-# This function should be called to get the compile definitions
-# suitable for working around MSVC to compile GMock, if any.
-# Returns a string of options in VARIABLE
-function(GET_MSVC_TUPLE_WORKAROUND_DEFINITIONS VARIABLE)
- set(${VARIABLE} "")
- if(MSVC AND MSVC_VERSION VERSION_EQUAL 1700)
- # Fixes Visual Studio 2012
- set(${VARIABLE} "_VARIADIC_MAX=10")
- endif()
- set(${VARIABLE} ${${VARIABLE}} PARENT_SCOPE)
-endfunction()
+# - Define macro to check if all of the following work:
+# sched_getaffinity()
+# sched_setaffinity()
+# CPU_ZERO()
+# CPU_SET()
+# CPU_ISSET()
+# CPU_CLR()
+# CPU_COUNT()
+
+# test_sched_affinity(VARIABLE)
+#
+# VARIABLE will be set to true if all of the functions link fine.
+
+MACRO(test_sched_affinity VARIABLE)
+
+ if(NOT DEFINED sched_affinity_compile)
+ MESSAGE(STATUS "Checking for sched.h GNU affinity API")
+
+ check_c_source_compiles(
+ "#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+#include <sched.h>
+int main(void) {
+ int i;
+ cpu_set_t mask;
+ CPU_ZERO(&mask);
+ sched_getaffinity(0, sizeof(cpu_set_t), &mask);
+ if(CPU_ISSET(0,&mask))
+ {
+ CPU_CLR(0,&mask);
+ CPU_SET(0,&mask);
+ }
+ sched_setaffinity(0, sizeof(cpu_set_t), &mask);
+ return CPU_COUNT(&mask);
+}" sched_affinity_compile)
+ endif(NOT DEFINED sched_affinity_compile)
+
+ if(sched_affinity_compile)
+ set(${VARIABLE} 1 CACHE INTERNAL "Result of test for sched.h GNU affinity API" FORCE)
+ else()
+ set(${VARIABLE} 0 CACHE INTERNAL "Result of test for sched.h GNU affinity API" FORCE)
+ endif()
+ENDMACRO(test_sched_affinity VARIABLE)
--- /dev/null
+#
+# This file is part of the GROMACS molecular simulation package.
+#
+# Copyright (c) 2014, by the GROMACS development team, led by
+# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+# and including many others, as listed in the AUTHORS file in the
+# top-level source directory and at http://www.gromacs.org.
+#
+# GROMACS is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; either version 2.1
+# of the License, or (at your option) any later version.
+#
+# GROMACS is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with GROMACS; if not, see
+# http://www.gnu.org/licenses, or write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# If you want to redistribute modifications to GROMACS, please
+# consider that scientific software is very special. Version
+# control is crucial - bugs must be traceable. We will be happy to
+# consider code for inclusion in the official distribution, but
+# derived work must not be called official GROMACS. Details are found
+# in the README & COPYING files - if they are missing, get the
+# official version at http://www.gromacs.org.
+#
+# To help us fund GROMACS development, we humbly ask that you cite
+# the research papers on the package. Check out http://www.gromacs.org.
+
+# GMock uses tuples extensively, but since it is part of tr1 we cannot
+# assume it is present - the Fujitsu compilers on K computer is one
+# example of a system where it is not, and this is likely the case for many
+# embedded systems too.
+#
+# In general, we can ask gmock to use its own internal implementation by
+# defining GTEST_USE_OWN_TR1_TUPLE=1. This is safe for Gromacs, since we do
+# not use tr1/tuple.h elsewhere. However, this workaround itself will not
+# compile on MSVC - but this is the only architecture we know where it does
+# not work. To make things even worse, on MSVC even the standard tr1/tuple
+# implementation is not fully compatible, but we can make it work by setting
+# _VARIADIC_MAX=10. This is similar to r675 of googletest, which is still not
+# present in GMock 1.7.0. See
+# https://code.google.com/p/googletest/source/detail?r=675#, but note
+# that its summary does not represent its code correctly.
+#
+# To make all this work without user intervention, we first check what compiler
+# we have, and if it is not MSVC we simply use the internal version. If we are
+# using MSVC, we rely on the compiler's version, but set the variable necessary
+# to make it compatible.
+#
+# This function should be called to get the compile definitions
+# suitable for making sure we have a tuple implementation that works with gmock.
+#
+# Returns a string of options in VARIABLE
+function(GET_GMOCK_TUPLE_WORKAROUND VARIABLE)
+ set(${VARIABLE} "")
+ if(MSVC OR (WIN32 AND CMAKE_CXX_COMPILER_ID MATCHES "Intel"))
+ if(MSVC_VERSION VERSION_EQUAL 1700)
+ # Fixes Visual Studio 2012
+ set(${VARIABLE} "_VARIADIC_MAX=10")
+ endif()
+ # For MSVC different from 2012, or Intel on Windows, we reply on tr1/tuple working.
+ else()
+ # Use the built-in version on all other compilers.
+ set(${VARIABLE} "GTEST_USE_OWN_TR1_TUPLE=1")
+ endif()
+ set(${VARIABLE} ${${VARIABLE}} PARENT_SCOPE)
+endfunction()
endif()
if (NOT _library_was_found AND NOT _find_quietly)
- message("${_message_text}A ${name} library was not found by CMake in the paths available to it. Falling back on the GROMACS internal version of the ${name} library instead. This is fine for normal usage.")
+ message(STATUS "${_message_text}Using GROMACS built-in ${name}.")
endif()
endif()
# code, *if* this code is recent enough (i.e., contains all changes from
# the corresponding code branch that affects the regression test
# results).
+# REGRESSIONTEST_MD5SUM
+# The MD5 checksum of the regressiontest tarball. Only used when building
+# from a source package.
# They are collected into a single section below.
# The following variables are set based on these:
# GMX_VERSION String composed from GMX_VERSION_* numeric variables
set(LIBRARY_VERSION ${LIBRARY_SOVERSION}.0.0)
set(REGRESSIONTEST_BRANCH "refs/heads/master")
+set(REGRESSIONTEST_MD5SUM "a07524afebca5013540d4f2f72df2dce")
#####################################################################
# General version management based on manually set numbers
`cmake -DGMX_BUILD_OWN_FFTW=ON`), or
* that you build FFTW from the source code.
-Note that the GROMACS-managed download of the FFTW tarball has a
-slight chance of posing a security risk. If you use this option, you
-will see a warning that advises how you can eliminate this risk
-(before the opportunity has arisen).
-
If you build FFTW from source yourself, get the most recent version
and follow its [installation
guide](http://www.fftw.org/doc/Installation-and-Customization.html#Installation-and-Customization).
/* Define to 1 if you have the sysconf() function */
#cmakedefine HAVE_SYSCONF
-/* Define to 1 if you have the sched_getaffinity() function */
-#cmakedefine HAVE_SCHED_GETAFFINITY
-
-/* Define to 1 if you have the sched_setaffinity() function */
-#cmakedefine HAVE_SCHED_SETAFFINITY
+/* Define to 1 if you have the all the affinity functions in sched.h */
+#cmakedefine HAVE_SCHED_AFFINITY
/* Bytes in IEEE fp word are in big-endian order if set, little-endian if not.
Only relevant when FLOAT_FORMAT_IEEE754 is defined. */
--- /dev/null
+fftw-download.cmake.cmakein !filter
# Machinery for running the external project
set(EXTERNAL_FFTW_VERSION 3.3.3)
# cmake make eats slashes //// -> //
-set(GMX_BUILD_OWN_FFTW_URL "http:////www.fftw.org/fftw-${EXTERNAL_FFTW_VERSION}.tar.gz" CACHE PATH "URL from where to download fftw, (use an absolute path when offline)")
-mark_as_advanced(GMX_BUILD_OWN_FFTW_URL)
-set(EXTERNAL_FFTW_MD5SUM 0a05ca9c7b3bfddc8278e7c40791a1c2)
-set (EXTERNAL_FFTW_BUILD_TARGET fftwBuild)
+set(GMX_BUILD_OWN_FFTW_URL
+ "http:////www.fftw.org/fftw-${EXTERNAL_FFTW_VERSION}.tar.gz" CACHE PATH
+ "URL from where to download fftw (use an absolute path when offline, adjust GMX_BUILD_OWN_FFTW_MD5 if downloading other version than ${EXTERNAL_FFTW_VERSION})")
+set(GMX_BUILD_OWN_FFTW_MD5 0a05ca9c7b3bfddc8278e7c40791a1c2 CACHE STRING
+ "Expected MD5 hash for the file at GMX_BUILD_OWN_FFTW_URL")
+mark_as_advanced(GMX_BUILD_OWN_FFTW_URL GMX_BUILD_OWN_FFTW_MD5)
+
+# ExternalProject at least up to CMake 3.0 prints a confusing error message if
+# download fails when MD5 verification is enabled. So we manage the download
+# ourselves so that MD5 sum is not verified there, and then pass a local file
+# as the URL to ExternalProject. This way, ExternalProject still verifies the
+# MD5 sum with a proper message if that fails.
+set(url "${GMX_BUILD_OWN_FFTW_URL}")
+# Determine whether we are actually downloading (this matches the conditions in
+# ExternalProject). ExternalProject works as expected if passed a local file.
+set(is_download TRUE)
+if (IS_DIRECTORY "${url}" OR "${url}" MATCHES "^file://" OR NOT "${url}" MATCHES "^[a-z]+://")
+ set(is_download FALSE)
+endif()
+if (is_download)
+ # For simplicity, don't try to extract the file name from the URL, but use
+ # a hard-coded value.
+ set(remote_url "${GMX_BUILD_OWN_FFTW_URL}")
+ set(local_path "${CMAKE_CURRENT_BINARY_DIR}/fftw.tar.gz")
+ set(url ${local_path})
+ # Write a script to do our own download step (mimics what ExternalProject
+ # would do, but without MD5 sum verification at this step).
+ set(download_script ${CMAKE_CURRENT_BINARY_DIR}/fftw-download.cmake)
+ configure_file(fftw-download.cmake.cmakein ${download_script} @ONLY)
+endif()
+
+# The actual build target.
+set(EXTERNAL_FFTW_BUILD_TARGET fftwBuild)
include(ExternalProject)
-# TODO in master branch - show this warning only on the first run
-# by using gmx_check_if_changed_result from I21b791ab8e4f3 when
-# that becomes available
-message(WARNING "The GROMACS build will download FFTW ${EXTERNAL_FFTW_VERSION} as requested, but it will not know the file it receives is correct. If you now use\nmake\n GROMACS will build and link to FFTW anyway, but there is a possible security risk if you execute a GROMACS tool that calls this library. Instead, you can use\nmake ${EXTERNAL_FFTW_BUILD_TARGET}\n to do just the download and build of FFTW, and then run\nmd5sum src/contrib/fftw/${EXTERNAL_FFTW_BUILD_TARGET}-prefix/src/fftw-${EXTERNAL_FFTW_VERSION}.tar.gz\nto see if it matches ${EXTERNAL_FFTW_MD5SUM}. If so, everything is OK and you should use \nmake\n to proceed with the rest of the GROMACS build. Alternatively, you could stop using GMX_BUILD_OWN_FFTW, and instead follow the GROMACS installation instructions to build FFTW yourself.")
-# TODO if/when CMake fixes http://www.cmake.org/Bug/view.php?id=14330
-# (ie. at least version > 2.8.11.2), consider reverting to using an
-# md5sum check to avoid needing the above warning
- ExternalProject_add(${EXTERNAL_FFTW_BUILD_TARGET}
- URL "${GMX_BUILD_OWN_FFTW_URL}"
+ExternalProject_add(${EXTERNAL_FFTW_BUILD_TARGET}
+ URL "${url}" URL_MD5 ${GMX_BUILD_OWN_FFTW_MD5}
CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=<INSTALL_DIR> --libdir=<INSTALL_DIR>/lib --disable-fortran
${GMX_BUILD_OWN_FFTW_SHARED_FLAG} ${GMX_BUILD_OWN_FFTW_OPTIMIZATION_CONFIGURATION}
${GMX_BUILD_OWN_FFTW_PREC}
${GMX_BUILD_OWN_FFTW_TARGET_HOST})
-externalproject_get_property(${EXTERNAL_FFTW_BUILD_TARGET} INSTALL_DIR)
+# Add a custom step to do our own download if that is necessary.
+if (is_download)
+ ExternalProject_add_step(${EXTERNAL_FFTW_BUILD_TARGET} pre-download
+ COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/fftw-download.cmake
+ DEPENDERS download)
+endif()
+
+ExternalProject_get_property(${EXTERNAL_FFTW_BUILD_TARGET} INSTALL_DIR)
string(TOUPPER "${FFTW}" UPPERFFTW)
string(TOLOWER "${FFTW}" LOWERFFTW)
--- /dev/null
+# Custom download script for Gromacs external FFTW build.
+
+# Mimics a similar script generated by CMake ExternalProject package, but
+# does not verify the MD5 sum (which would give confusing error messages if the
+# download fails).
+message(STATUS "downloading...
+ src='@remote_url@'
+ dest='@local_path@'")
+file(DOWNLOAD "@remote_url@" "@local_path@"
+ SHOW_PROGRESS STATUS status LOG log)
+list(GET status 0 status_code)
+list(GET status 1 status_string)
+if (NOT status_code EQUAL 0)
+ message(FATAL_ERROR "error: downloading '@remote_url@' failed
+ status_code: ${status_code}
+ status_string: ${status_string}
+ log: ${log}")
+endif()
+message(STATUS "downloading... done")
1) Download Boost (current minimal version is derived from 1.55.0)
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, scoped_ptr.hpp)
-5) delete source files which are not required. Currently:
- libs/smart_ptr/src/sp_collector.cpp
- libs/smart_ptr/src/sp_debug_hooks.cpp
+4) Make sure our subset works even with compilers not listed
+ among the boost ones (in particular, Fujistu in native mode):
+ - Edit config/select_compiler_config.hpp to add the fallback
+ to a generic compiler capability file at the end.
+ - Add the generic compiler capability file config/compiler/generic.hpp
+5) run bcp with required files (currently exception/all.hpp, scoped_ptr.hpp)
+6) delete source files which are not required. Currently:
+ - libs/smart_ptr/src/sp_collector.cpp
+ - libs/smart_ptr/src/sp_debug_hooks.cpp
Make sure that they are really not needed.If any source files are added make sure to add them to cmake.
--- /dev/null
+// File created by Erik Lindahl July 2014 by copying most of the pathscale.hpp
+// compiler definition in Boost-1.55.
+
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for most recent version.
+
+// Settings for a generic compiler. We assume that long long exists,
+// remove all C++11 support, and assume threads work.
+
+#ifndef BOOST_COMPILER
+# define BOOST_COMPILER "Generic compiler"
+#endif
+
+// It might seem stupid to assume a generic compiler to have threads, but it
+// appears some Boost reference counting might not be thread-safe without this.
+#define BOOST_HAS_THREADS
+#define BOOST_HAS_PTHREADS
+
+#define BOOST_HAS_LONG_LONG
+#define BOOST_NO_CXX11_VARIADIC_TEMPLATES
+#define BOOST_NO_CXX11_UNICODE_LITERALS
+#define BOOST_NO_CXX11_TEMPLATE_ALIASES
+#define BOOST_NO_CXX11_STATIC_ASSERT
+#define BOOST_NO_SFINAE_EXPR
+#define BOOST_NO_CXX11_SCOPED_ENUMS
+#define BOOST_NO_CXX11_RVALUE_REFERENCES
+#define BOOST_NO_CXX11_RANGE_BASED_FOR
+#define BOOST_NO_CXX11_RAW_LITERALS
+#define BOOST_NO_CXX11_NULLPTR
+#define BOOST_NO_CXX11_NUMERIC_LIMITS
+#define BOOST_NO_CXX11_NOEXCEPT
+#define BOOST_NO_CXX11_LAMBDAS
+#define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS
+#define BOOST_NO_MS_INT64_NUMERIC_LIMITS
+#define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS
+#define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
+#define BOOST_NO_CXX11_DELETED_FUNCTIONS
+#define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
+#define BOOST_NO_CXX11_DECLTYPE
+#define BOOST_NO_CXX11_DECLTYPE_N3276
+#define BOOST_NO_CXX11_CONSTEXPR
+#define BOOST_NO_COMPLETE_VALUE_INITIALIZATION
+#define BOOST_NO_CXX11_CHAR32_T
+#define BOOST_NO_CXX11_CHAR16_T
+#define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS
+#define BOOST_NO_CXX11_AUTO_DECLARATIONS
+#define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
+#define BOOST_NO_CXX11_HDR_UNORDERED_SET
+#define BOOST_NO_CXX11_HDR_UNORDERED_MAP
+#define BOOST_NO_CXX11_HDR_TYPEINDEX
+#define BOOST_NO_CXX11_HDR_TUPLE
+#define BOOST_NO_CXX11_HDR_THREAD
+#define BOOST_NO_CXX11_HDR_SYSTEM_ERROR
+#define BOOST_NO_CXX11_HDR_REGEX
+#define BOOST_NO_CXX11_HDR_RATIO
+#define BOOST_NO_CXX11_HDR_RANDOM
+#define BOOST_NO_CXX11_HDR_MUTEX
+#define BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+#define BOOST_NO_CXX11_HDR_FUTURE
+#define BOOST_NO_CXX11_HDR_FORWARD_LIST
+#define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE
+#define BOOST_NO_CXX11_HDR_CODECVT
+#define BOOST_NO_CXX11_HDR_CHRONO
+#define BOOST_NO_CXX11_USER_DEFINED_LITERALS
+#define BOOST_NO_CXX11_ALIGNAS
+#define BOOST_NO_CXX11_TRAILING_RESULT_TYPES
+#define BOOST_NO_CXX11_INLINE_NAMESPACES
+
// example) also #define _MSC_VER
# define BOOST_COMPILER_CONFIG "boost/config/compiler/visualc.hpp"
-#elif defined (BOOST_ASSERT_CONFIG)
-// this must come last - generate an error if we don't
-// recognise the compiler:
-# 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)"
+#else
+
+# warning Unknown boost compiler; using generic settings not tested for this compiler.
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/generic.hpp"
+
#endif
# As stated in README.Gromacs, this file is not part of GMock, but is written
# specifically for the GROMACS build system from scratch.
-include(gmxGetMsvcTupleWorkaround)
-get_msvc_tuple_workaround_definitions(GMOCK_COMPILE_DEFINITIONS)
+include(gmxGetGmockTupleWorkaround)
+get_gmock_tuple_workaround(GMOCK_COMPILE_DEFINITIONS)
set(GMOCK_COMPILE_DEFINITIONS ${GMOCK_COMPILE_DEFINITIONS} PARENT_SCOPE)
# GTest/GMock suggest linking with pthreads when available for thread safety
The file CMakeLists.txt in this directory is part of the Gromacs build system
and has been written from scratch.
+
+In the default version, gmock-1.7.0 assumes wcscasecmp() to be present on Linux.
+This is not the case on all platforms, so on line 1610 of gtest/src/gtest.cc
+we have added a define to only use this if GTEST_HAS_WCSCASECMP is set. Since
+we never set this define, we fall back on the alternative internal implementation
+which should be perfectly fine for now.
#if GTEST_OS_WINDOWS
return _wcsicmp(lhs, rhs) == 0;
-#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID
+#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID && GTEST_HAS_WCSCASECMP
return wcscasecmp(lhs, rhs) == 0;
#else
// Android, Mac OS X and Cygwin don't define wcscasecmp.
#elif defined(__FUJITSU) && defined(__sparc__)
/* Fujitsu FX10 SPARC compiler requires gcc compatibility with -Xg */
-#error Atomics support for Fujitsu FX10 compiler requires -Xg (gcc compatibility)
+#warning Atomics support for Fujitsu FX10 compiler requires -Xg (gcc compatibility)
+#define TMPI_NO_ATOMICS
#elif defined(_CRAYC)
void *newval)
{
void* prev;
-#ifndef __x86_64__
- __asm__ __volatile__("lock ; cmpxchgl %1,%2"
+#if (defined(__x86_64__) && !defined(__ILP32__))
+ __asm__ __volatile__("lock ; cmpxchgq %1,%2"
: "=a" (prev)
: "q" (newval), "m" (a->value), "0" (oldval)
: "memory");
-#else
- __asm__ __volatile__("lock ; cmpxchgq %1,%2"
+#elif (defined(__x86_64__) && defined(__ILP32__)) || defined(__i386__)
+ __asm__ __volatile__("lock ; cmpxchgl %1,%2"
: "=a" (prev)
: "q" (newval), "m" (a->value), "0" (oldval)
: "memory");
+#else
+# error Cannot detect whether this is a 32-bit or 64-bit x86 build.
#endif
return prev == oldval;
}
static inline void *tMPI_Atomic_ptr_swap(tMPI_Atomic_ptr_t *a, void *b)
{
void *volatile *ret = (void* volatile*)b;
-#ifndef __LP64__
- __asm__ __volatile__("\txchgl %0, %1;"
+#if (defined(__x86_64__) && !defined(__ILP32__))
+ __asm__ __volatile__("\txchgq %0, %1;"
: "+r" (ret), "+m" (a->value)
:
: "memory");
-
-#else
- __asm__ __volatile__("\txchgq %0, %1;"
+#elif (defined(__x86_64__) && defined(__ILP32__)) || defined(__i386__)
+ __asm__ __volatile__("\txchgl %0, %1;"
: "+r" (ret), "+m" (a->value)
:
: "memory");
+#else
+# error Cannot detect whether this is a 32-bit or 64-bit x86 build.
#endif
return (void*)ret;
}
= value_.begin() + index * columnCount();
return AnalysisDataFrameRef(
AnalysisDataFrameHeader(index, xvalue(index), 0.0),
- AnalysisDataValuesRef(begin, begin + columnCount()),
- AnalysisDataPointSetInfosRef(&pointSetInfo_, 1));
+ constArrayRefFromVector<AnalysisDataValue>(begin, begin + columnCount()),
+ constArrayRefFromArray(&pointSetInfo_, 1));
}
modules.notifyPointsAdd(
AnalysisDataPointSetRef(
header, pointSetInfo_,
- AnalysisDataValuesRef(valueIter,
- valueIter + columnCount())));
+ constArrayRefFromVector<AnalysisDataValue>(valueIter,
+ valueIter + columnCount())));
modules.notifyFrameFinish(header);
}
modules.notifyDataFinish();
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
: header_(header),
dataSetIndex_(pointSetInfo.dataSetIndex()),
firstColumn_(pointSetInfo.firstColumn()),
- values_(&*values.begin() + pointSetInfo.valueOffset(),
- pointSetInfo.valueCount())
+ values_(constArrayRefFromArray(&*values.begin() + pointSetInfo.valueOffset(),
+ pointSetInfo.valueCount()))
{
GMX_ASSERT(header_.isValid(),
"Invalid point set reference should not be constructed");
const AnalysisDataFrameHeader &header,
const std::vector<AnalysisDataValue> &values)
: header_(header), dataSetIndex_(0), firstColumn_(0),
- values_(values.begin(), values.end())
+ values_(constArrayRefFromVector<AnalysisDataValue>(values.begin(), values.end()))
{
GMX_ASSERT(header_.isValid(),
"Invalid point set reference should not be constructed");
const AnalysisDataFrameHeader &header,
const std::vector<AnalysisDataValue> &values,
const std::vector<AnalysisDataPointSetInfo> &pointSets)
- : header_(header), values_(values.begin(), values.end()),
- pointSets_(pointSets.begin(), pointSets.end())
+ : header_(header), values_(constArrayRefFromVector<AnalysisDataValue>(values.begin(), values.end())),
+ pointSets_(constArrayRefFromVector<AnalysisDataPointSetInfo>(pointSets.begin(), pointSets.end()))
{
GMX_ASSERT(!pointSets_.empty(), "There must always be a point set");
}
AnalysisDataFrameRef::AnalysisDataFrameRef(
const AnalysisDataFrameRef &frame, int firstColumn, int columnCount)
: header_(frame.header()),
- values_(&frame.values_[firstColumn], columnCount),
+ values_(constArrayRefFromArray(&frame.values_[firstColumn], columnCount)),
pointSets_(frame.pointSets_)
{
// FIXME: This doesn't produce a valid internal state, although it does
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
AnalysisDataPointSetInfo pointSetInfo(0, valueCount,
dataSetIndex, firstColumn);
AnalysisDataPointSetRef pointSet(header(), pointSetInfo,
- AnalysisDataValuesRef(begin, end));
+ constArrayRefFromVector<AnalysisDataValue>(begin, end));
storageImpl().modules_->notifyParallelPointsAdd(pointSet);
if (storageImpl().shouldNotifyImmediately())
{
"Invalid point set index");
return AnalysisDataPointSetRef(
header_, pointSets_[index],
- AnalysisDataValuesRef(values_.begin(), values_.end()));
+ constArrayRefFromVector<AnalysisDataValue>(values_.begin(), values_.end()));
}
} // namespace internal
fileOptManager.disableInputOptionChecking(
FF(PCA_NOT_READ_NODE) || FF(PCA_DISABLE_INPUT_FILE_CHECKING));
options.addManager(&fileOptManager);
- options.setDescription(gmx::ConstArrayRef<const char *>(desc, ndesc));
+ options.setDescription(gmx::constArrayRefFromArray<const char *>(desc, ndesc));
options.addOption(
gmx::IntegerOption("nice").store(&nicelevel)
gmx::CommandLineHelpWriter(options)
.setShowDescriptions(true)
.setTimeUnitString(timeUnitManager.timeUnitAsString())
- .setKnownIssues(gmx::ConstArrayRef<const char *>(bugs, nbugs))
+ .setKnownIssues(gmx::constArrayRefFromArray(bugs, nbugs))
.writeHelp(*context);
return FALSE;
}
#endif
#ifdef HAVE_SCHED_H
-#define _GNU_SOURCE
-#include <sched.h>
+# ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+# endif
+# include <sched.h>
#endif
#include <stdio.h>
/* Query APIC information on AMD */
if (max_extfn >= 0x80000008)
{
-#if (defined HAVE_SCHED_H && defined HAVE_SCHED_SETAFFINITY && defined HAVE_SYSCONF && defined __linux__)
+#if (defined HAVE_SCHED_AFFINITY && defined HAVE_SYSCONF && defined __linux__)
/* Linux */
unsigned int i;
cpu_set_t cpuset, save_cpuset;
if (max_stdfn >= 0xB)
{
/* Query x2 APIC information from cores */
-#if (defined HAVE_SCHED_H && defined HAVE_SCHED_SETAFFINITY && defined HAVE_SYSCONF && defined __linux__)
+#if (defined HAVE_SCHED_AFFINITY && defined HAVE_SYSCONF && defined __linux__)
/* Linux */
unsigned int i;
cpu_set_t cpuset, save_cpuset;
* the research papers on the package. Check out http://www.gromacs.org.
*/
#include "config.h"
-#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GETAFFINITY)
-#define _GNU_SOURCE
-#include <sched.h>
-#include <sys/syscall.h>
+#if defined(HAVE_SCHED_H)
+# ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+# endif
+# include <sched.h>
+# include <sys/syscall.h>
#endif
#include <string.h>
#include <errno.h>
int gmx_unused nthreads_hw_avail,
gmx_bool bAfterOpenmpInit)
{
-#ifdef HAVE_SCHED_GETAFFINITY
+#ifdef HAVE_SCHED_AFFINITY
cpu_set_t mask_current;
int i, ret, cpu_count, cpu_set;
gmx_bool bAllSet;
fprintf(debug, "Default affinity mask found\n");
}
}
-#endif /* HAVE_SCHED_GETAFFINITY */
+#endif /* HAVE_SCHED_AFFINITY */
}
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));
+ sprintf(err_buf, "TPI does not work (yet) with the Verlet cut-off scheme");
+ CHECK(ir->cutoff_scheme == ecutsVERLET);
}
/* SHAKE / LINCS */
/* Initialize the PME-only side of the PME <-> PP communication */
void gmx_pme_send_parameters(t_commrec *cr,
+ const interaction_const_t *ic,
gmx_bool bFreeEnergy_q, gmx_bool bFreeEnergy_lj,
real *chargeA, real *chargeB,
real *sqrt_c6A, real *sqrt_c6B,
if (!(cr->duty & DUTY_PME))
{
/* Send the charges and/or c6/sigmas to our PME only node */
- gmx_pme_send_parameters(cr, mdatoms->nChargePerturbed, mdatoms->nTypePerturbed,
+ gmx_pme_send_parameters(cr,
+ fr->ic,
+ mdatoms->nChargePerturbed, mdatoms->nTypePerturbed,
mdatoms->chargeA, mdatoms->chargeB,
mdatoms->sqrt_c6A, mdatoms->sqrt_c6B,
mdatoms->sigmaA, mdatoms->sigmaB,
#endif
#endif
- /* Mask for the cut-off to avoid overflow in gmx_simd_exp_r */
+ /* Mask for the cut-off to avoid overflow of cr2^2 */
cr2_S0 = gmx_simd_mul_r(lje_c2_S, gmx_simd_blendzero_r(rsq_S0, wco_vdw_S0));
#ifndef HALF_LJ
cr2_S2 = gmx_simd_mul_r(lje_c2_S, gmx_simd_blendzero_r(rsq_S2, wco_vdw_S2));
#endif
#endif
- /* Mask for the cut-off to avoid overflow in gmx_simd_exp_r */
+ /* Mask for the cut-off to avoid overflow of cr2^2 */
cr2_S0 = gmx_simd_mul_r(lje_c2_S, gmx_simd_blendzero_r(rsq_S0, wco_vdw_S0));
cr2_S1 = gmx_simd_mul_r(lje_c2_S, gmx_simd_blendzero_r(rsq_S1, wco_vdw_S1));
#ifndef HALF_LJ
*/
ndx = 0;
ndx_excl = 0;
+#if __ICC == 1400 || __ICL == 1400
+#pragma novector /* Work-around for incorrect vectorization */
+#endif
for (mb = 0; mb < mtop->nmolblock; mb++)
{
molt = &mtop->moltype[mtop->molblock[mb].type];
if (bCommY)
{
commbuf = commbuf_y;
- buf_my = ty1 - offy;
+ /* The y-size of the communication buffer is order-1 */
+ buf_my = pmegrid->order - 1;
if (bCommX)
{
/* We index commbuf modulo the local grid size */
if (debug)
{
- fprintf(debug, "PP rank %d sending to PME rank %d: %d%s%s\n",
+ fprintf(debug, "PP rank %d sending to PME rank %d: %d%s%s%s%s\n",
cr->sim_nodeid, dd->pme_nodeid, n,
flags & PP_PME_CHARGE ? " charges" : "",
+ flags & PP_PME_SQRTC6 ? " sqrtC6" : "",
+ flags & PP_PME_SIGMA ? " sigma" : "",
flags & PP_PME_COORD ? " coordinates" : "");
}
}
void gmx_pme_send_parameters(t_commrec *cr,
+ const interaction_const_t *ic,
gmx_bool bFreeEnergy_q, gmx_bool bFreeEnergy_lj,
real *chargeA, real *chargeB,
real *sqrt_c6A, real *sqrt_c6B,
{
int flags;
- /* We always send the charges, even with only LJ- and no Coulomb-PME */
- flags = PP_PME_CHARGE;
- if (sqrt_c6A != NULL)
+ flags = 0;
+ if (EEL_PME(ic->eeltype))
{
- flags |= PP_PME_SQRTC6;
+ flags |= PP_PME_CHARGE;
}
- if (sigmaA != NULL)
+ if (EVDW_PME(ic->vdwtype))
{
- flags |= PP_PME_SIGMA;
+ flags |= (PP_PME_SQRTC6 | PP_PME_SIGMA);
}
if (bFreeEnergy_q || bFreeEnergy_lj)
{
nat += pme_pp->nat[sender];
if (debug)
{
- fprintf(debug, "Received from PP rank %d: %d "
- "charges\n",
- pme_pp->node[sender], pme_pp->nat[sender]);
+ fprintf(debug, "Received from PP rank %d: %d %s\n",
+ pme_pp->node[sender], pme_pp->nat[sender],
+ (q == eCommType_ChargeA ||
+ q == eCommType_ChargeB) ? "charges" : "params");
}
}
}
real bU_bin_limit = 50;
real bU_logV_bin_limit = bU_bin_limit + 10;
+ if (inputrec->cutoff_scheme == ecutsVERLET)
+ {
+ gmx_fatal(FARGS, "TPI does not work (yet) with the Verlet cut-off scheme");
+ }
+
nnodes = cr->nnodes;
top = gmx_mtop_generate_local_top(top_global, inputrec);
std::string toUpperCase(const std::string &text)
{
std::string result(text);
- transform(result.begin(), result.end(), result.begin(), toupper);
+ std::transform(result.begin(), result.end(), result.begin(), toupper);
return result;
}
const int genericTypeCount = ftp2generic_count(fileType_);
if (genericTypeCount > 0)
{
- return ConstArrayRef<int>(ftp2generic_list(fileType_), genericTypeCount);
+ return constArrayRefFromArray<int>(ftp2generic_list(fileType_), genericTypeCount);
}
- return ConstArrayRef<int>(&fileType_, 1);
+ return constArrayRefFromArray<int>(&fileType_, 1);
}
/********************************************************************
"Exclusion IDs must be set when exclusions are enabled");
if (positions.index_ < 0)
{
- testPositions_ = ConstArrayRef<rvec>(positions.x_, positions.count_);
+ testPositions_ = constArrayRefFromArray<rvec>(positions.x_, positions.count_);
reset(0);
}
else
{
// Somewhat of a hack: setup the array such that only the last position
// will be used.
- testPositions_ = ConstArrayRef<rvec>(positions.x_, positions.index_ + 1);
+ testPositions_ = constArrayRefFromArray<rvec>(positions.x_, positions.index_ + 1);
reset(positions.index_);
}
}
if (sel_->hasOnlyAtoms())
{
// TODO: Move atomIndices() such that it can be reused here as well.
- pos.exclusionIds(ConstArrayRef<int>(sel_->rawPositions_.m.mapb.a,
- sel_->rawPositions_.m.mapb.nra));
+ pos.exclusionIds(constArrayRefFromArray<int>(sel_->rawPositions_.m.mapb.a,
+ sel_->rawPositions_.m.mapb.nra));
}
return pos.selectSingleFromArray(i_);
}
//! Returns atom indices of all atoms in the selection.
ConstArrayRef<int> atomIndices() const
{
- return ConstArrayRef<int>(sel_->rawPositions_.m.mapb.a,
- sel_->rawPositions_.m.mapb.nra);
+ return constArrayRefFromArray(sel_->rawPositions_.m.mapb.a,
+ sel_->rawPositions_.m.mapb.nra);
}
//! Number of positions in the selection.
int posCount() const { return data().posCount(); }
//! Returns coordinates for this selection as a continuous array.
ConstArrayRef<rvec> coordinates() const
{
- return ConstArrayRef<rvec>(data().rawPositions_.x, posCount());
+ return constArrayRefFromArray(data().rawPositions_.x, posCount());
}
//! Returns whether velocities are available for this selection.
bool hasVelocities() const { return data().rawPositions_.v != NULL; }
ConstArrayRef<rvec> velocities() const
{
GMX_ASSERT(hasVelocities(), "Velocities accessed, but unavailable");
- return ConstArrayRef<rvec>(data().rawPositions_.v, posCount());
+ return constArrayRefFromArray(data().rawPositions_.v, posCount());
}
//! Returns whether forces are available for this selection.
bool hasForces() const { return sel_->rawPositions_.f != NULL; }
ConstArrayRef<rvec> forces() const
{
GMX_ASSERT(hasForces(), "Forces accessed, but unavailable");
- return ConstArrayRef<rvec>(data().rawPositions_.f, posCount());
+ return constArrayRefFromArray(data().rawPositions_.f, posCount());
}
//! Returns masses for this selection as a continuous array.
ConstArrayRef<real> masses() const
// (and thus the masses and charges are fixed).
GMX_ASSERT(data().posMass_.size() >= static_cast<size_t>(posCount()),
"Internal inconsistency");
- return ConstArrayRef<real>(data().posMass_.begin(),
- data().posMass_.begin() + posCount());
+ return constArrayRefFromVector<real>(data().posMass_.begin(),
+ data().posMass_.begin() + posCount());
}
//! Returns charges for this selection as a continuous array.
ConstArrayRef<real> charges() const
// (and thus the masses and charges are fixed).
GMX_ASSERT(data().posCharge_.size() >= static_cast<size_t>(posCount()),
"Internal inconsistency");
- return ConstArrayRef<real>(data().posCharge_.begin(),
- data().posCharge_.begin() + posCount());
+ return constArrayRefFromVector<real>(data().posCharge_.begin(),
+ data().posCharge_.begin() + posCount());
}
/*! \brief
* Returns reference IDs for this selection as a continuous array.
*/
ConstArrayRef<int> refIds() const
{
- return ConstArrayRef<int>(data().rawPositions_.m.refid, posCount());
+ return constArrayRefFromArray(data().rawPositions_.m.refid, posCount());
}
/*! \brief
* Returns mapped IDs for this selection as a continuous array.
*/
ConstArrayRef<int> mappedIds() const
{
- return ConstArrayRef<int>(data().rawPositions_.m.mapid, posCount());
+ return constArrayRefFromArray(data().rawPositions_.m.mapid, posCount());
}
//! Returns whether the covered fraction can change between frames.
return ConstArrayRef<int>();
}
const int first = sel_->rawPositions_.m.mapb.index[i_];
- return ConstArrayRef<int>(&atoms[first], atomCount());
+ return constArrayRefFromArray(&atoms[first], atomCount());
}
/*! \brief
* Returns whether this position is selected in the current frame.
gmx::ConstArrayRef<int> refPosIds() const
{
- return gmx::ConstArrayRef<int>(exclusionIds_.begin(),
- exclusionIds_.begin() + refPosCount_);
+ return gmx::constArrayRefFromVector<int>(exclusionIds_.begin(),
+ exclusionIds_.begin() + refPosCount_);
}
gmx::ConstArrayRef<int> testPosIds() const
{
- return gmx::ConstArrayRef<int>(exclusionIds_.begin(),
- exclusionIds_.begin() + testPosCount_);
+ return gmx::constArrayRefFromVector<int>(exclusionIds_.begin(),
+ exclusionIds_.begin() + testPosCount_);
}
private:
* extended precision arithmetics to improve accuracy.
*
* \param x Argument.
- * \result exp(x). Undefined if input argument caused overflow.
+ * \result exp(x). Undefined if input argument caused overflow,
+ * which can happen if abs(x) \> 7e13.
*/
static gmx_inline gmx_simd_float_t
gmx_simd_exp_f(gmx_simd_float_t x)
* that we can leave out of this routine.
*
* For pme tolerances of 1e-3 to 1e-8 and cutoffs of 0.5nm to 1.8nm,
- * the argument \f$beta r\f$ will be in the range 0.15 to ~4. Use your
- * favorite plotting program to realize how well-behaved \f$\frac{\mbox{erf}(z)}{z}\f$ is
- * in this range!
+ * the argument \f$beta r\f$ will be in the range 0.15 to ~4, which is
+ * the range used for the minimax fit. Use your favorite plotting program
+ * to realize how well-behaved \f$\frac{\mbox{erf}(z)}{z}\f$ is in this range!
*
* We approximate \f$f(z)=\mbox{erf}(z)/z\f$ with a rational minimax polynomial.
* However, it turns out it is more efficient to approximate \f$f(z)/z\f$ and
* with the vector connecting the two particles and you have your
* vectorial force to add to the particles.
*
- * This approximation achieves an accuracy slightly lower than 1e-6; when
- * added to \f$1/r\f$ the error will be insignificant.
+ * This approximation achieves an error slightly lower than 1e-6
+ * in single precision and 1e-11 in double precision
+ * for arguments smaller than 16 (\f$\beta r \leq 4 \f$);
+ * when added to \f$1/r\f$ the error will be insignificant.
+ * For \f$\beta r \geq 7206\f$ the return value can be inf or NaN.
*
*/
static gmx_simd_float_t
* 6. Subtract the result from \f$1/r\f$, multiply by the product of the charges,
* and you have your potential.
*
- * This approximation achieves an accuracy slightly lower than 1e-6; when
- * added to \f$1/r\f$ the error will be insignificant.
+ * This approximation achieves an error slightly lower than 1e-6
+ * in single precision and 4e-11 in double precision
+ * for arguments smaller than 16 (\f$ 0.15 \leq \beta r \leq 4 \f$);
+ * for \f$ \beta r \leq 0.15\f$ the error can be twice as high;
+ * when added to \f$1/r\f$ the error will be insignificant.
+ * For \f$\beta r \geq 7142\f$ the return value can be inf or NaN.
*/
static gmx_simd_float_t
gmx_simd_pmecorrV_f(gmx_simd_float_t z2)
{
setRange(-100, 100);
GMX_EXPECT_SIMD_FUNC_NEAR(ref_exp2, gmx_simd_exp2_r);
+
+ // We do not care about the SIMD implementation getting denormal values right,
+ // but they must be clamped to zero rather than producing garbage.
+ // Check by setting the absolute tolerance to machine precision.
+ setAbsTol(GMX_REAL_EPS);
+
+ // First two values will have denormal results in single, third value in double too.
+ GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(ref_exp2(-150.0), ref_exp2(-300.0), ref_exp2(-1050.0)),
+ gmx_simd_exp2_r(setSimdRealFrom3R(-150.0, -300.0, -1050.0)));
+
+ // Reset absolute tolerance to enforce ULP checking
+ setAbsTol(0.0);
+
+ // Make sure that underflowing values are set to zero.
+ // First two values underflow in single, third value in double too.
+ GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(ref_exp2(-200.0), ref_exp2(-600.0), ref_exp2(-1500.0)),
+ gmx_simd_exp2_r(setSimdRealFrom3R(-200.0, -600.0, -1500.0)));
}
#endif
{
setRange(-75, 75);
GMX_EXPECT_SIMD_FUNC_NEAR(ref_exp, gmx_simd_exp_r);
+
+ // We do not care about the SIMD implementation getting denormal values right,
+ // but they must be clamped to zero rather than producing garbage.
+ // Check by setting the absolute tolerance to machine precision.
+ setAbsTol(GMX_REAL_EPS);
+ // First two values will have denormal results in single, third value in double too.
+ GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(ref_exp(-90.0), ref_exp(-100.0), ref_exp(-725.0)),
+ gmx_simd_exp_r(setSimdRealFrom3R(-90.0, -100.0, -725.0)));
+
+ // Reset absolute tolerance to enforce ULP checking
+ setAbsTol(0.0);
+
+ // Make sure that underflowing values are set to zero.
+ // First two values underflow in single, third value in double too.
+ GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(ref_exp(-150.0), ref_exp(-300.0), ref_exp(-800.0)),
+ gmx_simd_exp_r(setSimdRealFrom3R(-150.0, -300.0, -800.0)));
}
/*! \brief Function wrapper for erf(x), with argument/return in default Gromacs precision.
* \param[in] end Pointer to the end of a range.
*
* Passed pointers must remain valid for the lifetime of this object.
+ *
+ * \note For clarity, use the non-member function arrayRefFromPointers
+ * instead.
*/
ArrayRef(pointer begin, pointer end)
: begin_(begin), end_(end)
{
GMX_ASSERT(end >= begin, "Invalid range");
}
- /*! \brief
- * Constructs a reference to a particular range in a std::vector.
- *
- * \param[in] begin Iterator to the beginning of a range.
- * \param[in] end Iterator to the end of a range.
- *
- * The referenced vector must remain valid and not be reallocated for
- * the lifetime of this object.
- */
- ArrayRef(typename std::vector<value_type>::iterator begin,
- typename std::vector<value_type>::iterator end)
- : begin_((begin != end) ? &*begin : NULL),
- end_(begin_+(end-begin))
- {
- GMX_ASSERT(end >= begin, "Invalid range");
- }
- /*! \brief
- * Constructs a reference to an array.
- *
- * \param[in] begin Pointer to the beginning of the array.
- * May be NULL if \p size is zero.
- * \param[in] size Number of elements in the array.
- *
- * Passed pointer must remain valid for the lifetime of this object.
- */
- ArrayRef(pointer begin, size_type size)
- : begin_(begin), end_(begin + size)
- {
- }
//! \cond
// Doxygen 1.8.5 doesn't parse the declaration correctly...
/*! \brief
pointer end_;
};
+
+/*! \brief
+ * Constructs a reference to a particular range from two pointers.
+ *
+ * \param[in] begin Pointer to the beginning of a range.
+ * \param[in] end Pointer to the end of a range.
+ *
+ * Passed pointers must remain valid for the lifetime of this object.
+ *
+ * \related ArrayRef
+ */
+template <typename T>
+ArrayRef<T> arrayRefFromPointers(T * begin, T * end)
+{
+ return ArrayRef<T>(begin, end);
+}
+
+/*! \brief
+ * Constructs a reference to an array
+ *
+ * \param[in] begin Pointer to the beginning of the array.
+ * May be NULL if \p size is zero.
+ * \param[in] size Number of elements in the array.
+ *
+ * Passed pointer must remain valid for the lifetime of this object.
+ *
+ * \related ArrayRef
+ */
+template <typename T>
+ArrayRef<T> arrayRefFromArray(T * begin, size_t size)
+{
+ return arrayRefFromPointers<T>(begin, begin+size);
+}
+
+/*! \brief
+ * Constructs a reference to a particular range in a std::vector.
+ *
+ * \param[in] begin Iterator to the beginning of a range.
+ * \param[in] end Iterator to the end of a range.
+ *
+ * The referenced vector must remain valid and not be reallocated for
+ * the lifetime of this object.
+ *
+ * \related ArrayRef
+ */
+template <typename T>
+ArrayRef<T> arrayRefFromVector(typename std::vector<T>::iterator begin,
+ typename std::vector<T>::iterator end)
+{
+ T * p_begin = (begin != end) ? &*begin : NULL;
+ T * p_end = p_begin + (end-begin);
+ return arrayRefFromPointers<T>(p_begin, p_end);
+}
+
+
+
/*! \brief
* STL-like container for non-mutable interface to a C array (or part of a
* std::vector).
* \param[in] end Pointer to the end of a range.
*
* Passed pointers must remain valid for the lifetime of this object.
+ *
+ * \note For clarity, use the non-member function constArrayRefFromPointers
+ * instead.
*/
ConstArrayRef(const_pointer begin, const_pointer end)
: begin_(begin), end_(end)
{
GMX_ASSERT(end >= begin, "Invalid range");
}
- /*! \brief
- * Constructs a reference to a particular range in a std::vector.
- *
- * \param[in] begin Iterator to the beginning of a range.
- * \param[in] end Iterator to the end of a range.
- *
- * The referenced vector must remain valid and not be reallocated for
- * the lifetime of this object.
- */
- ConstArrayRef(typename std::vector<value_type>::const_iterator begin,
- typename std::vector<value_type>::const_iterator end)
- : begin_((begin != end) ? &*begin : NULL),
- end_(begin_+(end-begin))
- {
- GMX_ASSERT(end >= begin, "Invalid range");
- }
- /*! \brief
- * Constructs a reference to an array.
- *
- * \param[in] begin Pointer to the beginning of the array.
- * May be NULL if \p size is zero.
- * \param[in] size Number of elements in the array.
- *
- * Passed pointer must remain valid for the lifetime of this object.
- */
- ConstArrayRef(const_pointer begin, size_type size)
- : begin_(begin), end_(begin + size)
- {
- }
//! \cond
// Doxygen 1.8.5 doesn't parse the declaration correctly...
/*! \brief
const_pointer end_;
};
+
+/*! \brief
+ * Constructs a reference to a particular range from two pointers.
+ *
+ * \param[in] begin Pointer to the beginning of a range.
+ * \param[in] end Pointer to the end of a range.
+ *
+ * Passed pointers must remain valid for the lifetime of this object.
+ *
+ * \related ConstArrayRef
+ */
+template <typename T>
+ConstArrayRef<T> constArrayRefFromPointers(const T * begin, const T * end)
+{
+ return ConstArrayRef<T>(begin, end);
+}
+
+/*! \brief
+ * Constructs a reference to an array.
+ *
+ * \param[in] begin Pointer to the beginning of the array.
+ * May be NULL if \p size is zero.
+ * \param[in] size Number of elements in the array.
+ *
+ * Passed pointer must remain valid for the lifetime of this object.
+ *
+ * \related ConstArrayRef
+ */
+template <typename T>
+ConstArrayRef<T> constArrayRefFromArray(const T * begin, size_t size)
+{
+ return constArrayRefFromPointers<T>(begin, begin+size);
+}
+
+/*! \brief
+ * Constructs a reference to a particular range in a std::vector.
+ *
+ * \param[in] begin Iterator to the beginning of a range.
+ * \param[in] end Iterator to the end of a range.
+ *
+ * The referenced vector must remain valid and not be reallocated for
+ * the lifetime of this object.
+ *
+ * \related ConstArrayRef
+ */
+template <typename T>
+ConstArrayRef<T> constArrayRefFromVector(typename std::vector<T>::const_iterator begin,
+ typename std::vector<T>::const_iterator end)
+{
+ const T * p_begin = (begin != end) ? &*begin : NULL;
+ const T * p_end = p_begin + (end-begin);
+ return constArrayRefFromPointers<T>(p_begin, p_end);
+}
+
/*! \brief
* Simple swap method for ArrayRef objects.
*
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(TestUtilsUnitTests testutils-test
- refdata.cpp
- testasserts.cpp)
+ refdata_tests.cpp
+ testasserts_tests.cpp)
status_string: ${status_string}
log: ${log}")
endif()
+ if (SOURCE_IS_SOURCE_DISTRIBUTION)
+ file(MD5 ${REGRESSIONTEST_FILE} COMPUTED_MD5SUM)
+ if(NOT ${REGRESSIONTEST_MD5SUM} STREQUAL ${COMPUTED_MD5SUM})
+ message(FATAL_ERROR "Download of regressiontests failed. Expected MD5 of ${REGRESSIONTEST_MD5SUM} but download has ${COMPUTED_MD5SUM}")
+ endif()
+ endif()
file(REMOVE_RECURSE "${REGRESSIONTEST_PATH}") #delete potential prior folder
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${REGRESSIONTEST_FILE}"