Commit f442920e authored by Lynn Garren's avatar Lynn Garren
Browse files

Merge branch 'develop'

parents b0a8c36c a1059400
......@@ -3,7 +3,8 @@
# cmake [-DCMAKE_INSTALL_PREFIX=/install/path]
# [-DCMAKE_BUILD_TYPE=Debug|Release|RelWithDebInfo|MinSizeRel]
# [-DCMAKE_C_COMPILER=...] [-DCMAKE_CXX_COMPILER=...]
# [-DCLHEP_BUILD_CXXSTD="-std=c++NN"] (use specified c++ extension and thread support)
# [-DCMAKE_CXX_FLAGS=...]
# [-DCLHEP_BUILD_CXXSTD="-std=c++NN"] (use specified c++ extension)
# [-DCLHEP_DEBUG_MESSAGES=ON] (see more verbose output)
# [-DCLHEP_BUILD_DOCS=ON]
# [-DLIB_SUFFIX=64]
......@@ -26,12 +27,12 @@
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/ClhepOutOfSourceBuild.cmake)
clhep_ensure_out_of_source_build()
# use cmake 2.6 or later
cmake_minimum_required(VERSION 2.6)
# use cmake 3.2 or later
cmake_minimum_required(VERSION 3.2)
# project name
project(CLHEP)
set( VERSION 2.3.1.1 )
set( VERSION 2.3.2.1 )
# If Policy CMP0042 exists, use OLD to prefer the use of install names
# instead of the new @rpath default.
......
==============================
19.04.16 Release CLHEP-2.3.2.1
==============================
2016-04-19 Lynn Garren <garren@fnal.gov>
* gcc must be gcc 4.8 or better
* clang must be 3.5 or better
* cmake: Remove obsolete cmake macros
* cmake: Set CMAKE_SHARED_LINKER_FLAGS
* cmake: Use find_package(Threads)
2016-03-25 W. David Dagenhart <wdd@fnal.gov>
* Utility/Utility/use_atomic.h: Use std::atomic when the compiler declares it
uses the C++11 standard
2016-03-25 W. David Dagenhart <wdd@fnal.gov>
* Random/src/MixMaxRng.cc: The uncorrected code might not always yield independent seeds.
If two threads execute numberOfEngines++ and after both finish that both
execute setSeed, then they will have the same seed. Fixed.
* Random/src/Random.cc: There is a thread local variable of the type "defaults"
that contains two shared_ptr's in Random.cc. This causes an intermittent
problem on OSX. The complex objects containing the shared_ptr's have been
moved into a list of objects and the now the thread_local only contains a
simple pointer now that points into the list.
Use the new Utility/use_atomic.h header.
==============================
10.11.15 Release CLHEP-2.3.1.1
==============================
......
==============================
19.04.16 Release CLHEP-2.3.2.1
==============================
==============================
10.11.15 Release CLHEP-2.3.1.1
==============================
==============================
......
==============================
19.04.16 Release CLHEP-2.3.2.1
==============================
==============================
10.11.15 Release CLHEP-2.3.1.1
==============================
==============================
......
==============================
19.04.16 Release CLHEP-2.3.2.1
==============================
==============================
10.11.15 Release CLHEP-2.3.1.1
==============================
==============================
......
==============================
19.04.16 Release CLHEP-2.3.2.1
==============================
==============================
10.11.15 Release CLHEP-2.3.1.1
==============================
==============================
......
......@@ -49,11 +49,3 @@ int main(int, char **) {
std::cout << "GenericFunctions autotest has passed" << std::endl;
return 0;
}
#if defined __GNUC__
#if __GNUC__ > 3 && __GNUC_MINOR__ > 6
#pragma GCC diagnostic pop
#endif
#endif
#ifdef __clang__
#pragma clang diagnostic pop
#endif
==============================
19.04.16 Release CLHEP-2.3.2.1
==============================
==============================
10.11.15 Release CLHEP-2.3.1.1
==============================
==============================
......
==============================
19.04.16 Release CLHEP-2.3.2.1
==============================
==============================
10.11.15 Release CLHEP-2.3.1.1
==============================
==============================
......
==============================
19.04.16 Release CLHEP-2.3.2.1
==============================
2016-04-19 Lynn Garren <garren@fnal.gov>
* test/testRandDists.cc: found another shadowed variable
2016-03-25 W. David Dagenhart <wdd@fnal.gov>
* src/MixMaxRng.cc: The uncorrected code might not always yield independent seeds.
If two threads execute numberOfEngines++ and after both finish that both
execute setSeed, then they will have the same seed. Fixed.
* src/Random.cc: There is a thread local variable of the type "defaults"
that contains two shared_ptr's in Random.cc. This causes an intermittent
problem on OSX. The complex objects containing the shared_ptr's have been
moved into a list of objects and the now the thread_local only contains a
simple pointer now that points into the list.
Use the new Utility/use_atomic.h header.
==============================
10.11.15 Release CLHEP-2.3.1.1
==============================
......
......@@ -54,9 +54,9 @@ std::string MixMaxRng::name() const { return "MixMaxRng"; } // N=" + N
MixMaxRng::MixMaxRng()
: HepRandomEngine()
{
numberOfEngines++;
int numEngines = ++numberOfEngines;
fRngState= rng_alloc();
setSeed(static_cast<long>(numberOfEngines));
setSeed(static_cast<long>(numEngines));
}
MixMaxRng::MixMaxRng(long seed)
......
......@@ -25,6 +25,7 @@
#include "CLHEP/Random/StaticRandomStates.h"
#include "CLHEP/Utility/memory.h"
#include "CLHEP/Utility/thread_local.h"
#include "CLHEP/Utility/use_atomic.h"
// -----------------------------
// Static members initialisation
......@@ -34,43 +35,141 @@
namespace CLHEP {
namespace {
namespace {
struct defaults {
struct defaults {
defaults( HepRandom & g, HepJamesRandom & e )
: theGenerator( &g, do_nothing_deleter() )
, theEngine ( &e, do_nothing_deleter() )
{ }
defaults()
: theGenerator( &theDefaultGenerator, do_nothing_deleter() )
, theEngine ( &theDefaultEngine, do_nothing_deleter() )
{ }
void resetEngine( HepRandomEngine * newEngine ) {
theEngine.reset( newEngine );
}
defaults(defaults const& other) = delete;
defaults const& operator=(defaults const&) = delete;
void resetEngine( HepRandomEngine & newEngine ) {
theEngine.reset( &newEngine, do_nothing_deleter() );
}
void resetEngine( HepRandomEngine * newEngine ) {
theEngine.reset( newEngine );
}
bool ensureInitialized() {
assert( theGenerator.get() != 0 && theEngine.get() != 0 );
return true;
}
void resetEngine( HepRandomEngine & newEngine ) {
theEngine.reset( &newEngine, do_nothing_deleter() );
}
~defaults()
{ }
bool ensureInitialized() {
assert( theGenerator.get() != 0 && theEngine.get() != 0 );
return true;
}
std::shared_ptr<HepRandom > theGenerator;
std::shared_ptr<HepRandomEngine> theEngine;
}; // defaults
~defaults()
{ }
defaults & theDefaults() {
static CLHEP_THREAD_LOCAL HepRandom theDefaultGenerator;
static CLHEP_THREAD_LOCAL HepJamesRandom theDefaultEngine;
static CLHEP_THREAD_LOCAL defaults theDefaults(theDefaultGenerator, theDefaultEngine);
return theDefaults;
}
private:
HepRandom theDefaultGenerator;
HepJamesRandom theDefaultEngine;
public:
std::shared_ptr<HepRandom > theGenerator;
std::shared_ptr<HepRandomEngine> theEngine;
}; // defaults
#ifdef CLHEP_USE_ATOMIC
// The ThreadSafeDefaultCache is used only by the function named theDefaults.
// It is a singly linked list that is intended to hold one object of
// type "defaults" per thread.
class ThreadSafeDefaultsCache {
public:
ThreadSafeDefaultsCache();
// The destructor deletes the objects of type "defaults"
~ThreadSafeDefaultsCache();
// Creates new objects and adds them to the linked list in a thread safe manner.
defaults* createNewDefaults();
// Note that there are no other functions. No erasing or moving or other accessors.
} // namespace
private:
class DefaultsNode {
public:
DefaultsNode(DefaultsNode* iNext);
DefaultsNode const* next() const { return next_; }
void setNext(DefaultsNode* v) { next_ = v; }
defaults* addressOfDefaults() { return &defaults_; }
private:
DefaultsNode* next_;
defaults defaults_;
};
// points to first node in the linked list
std::atomic<DefaultsNode*> front_;
};
ThreadSafeDefaultsCache::ThreadSafeDefaultsCache() :
front_(nullptr) {
}
defaults* ThreadSafeDefaultsCache::createNewDefaults() {
DefaultsNode* expected = front_.load();
DefaultsNode* newNode = new DefaultsNode(expected);
while (!front_.compare_exchange_strong(expected, newNode)) {
// another thread changed front_ before us so try again
newNode->setNext(expected);
}
return newNode->addressOfDefaults();
}
ThreadSafeDefaultsCache::DefaultsNode::DefaultsNode(DefaultsNode* iNext) :
next_(iNext),
defaults_() {
}
ThreadSafeDefaultsCache::~ThreadSafeDefaultsCache() {
DefaultsNode const* node = front_.load();
while (node) {
DefaultsNode const* next = node->next();
delete node;
node = next;
}
}
defaults & theDefaults() {
// We need to have different engines on different threads because
// the engines are not thread safe. One cannot generate random numbers
// using the same engine on different threads simultaneously.
// Originally we had the defaults object itself as a thread local,
// but that was failing because on Mac OSX there is not full
// support for thread locals yet. Objects containing std::shared_ptr
// in thread local storage were causing failures. So now we create
// a container of them that is a function static (not thread local)
// and the thread local contains only a pointer to an object in the
// container.
static ThreadSafeDefaultsCache defaultsForAllThreads;
// A pointer for each thread to defaults object built for each thread.
static CLHEP_THREAD_LOCAL defaults* theDefaults = defaultsForAllThreads.createNewDefaults();
return *theDefaults;
}
#else
// This version is used with old compilers not supporting atomics.
// In that case, the code should not be executed in more than one thread.
defaults & theDefaults() {
static defaults theDefaults;
return theDefaults;
}
#endif
} // namespace
//---------------------------- HepRandom ---------------------------------
......@@ -92,7 +191,7 @@ HepRandom::HepRandom(HepRandomEngine * algorithm)
theDefaults().resetEngine( algorithm );
}
HepRandom::~HepRandom()
HepRandom::~HepRandom()
{ }
double HepRandom::flat()
......@@ -113,7 +212,7 @@ std::string HepRandom::name() const {return "HepRandom";}
HepRandomEngine & HepRandom::engine() {
std::cerr << "HepRandom::engine() called -- there is no assigned engine!\n";
return *theDefaults().theEngine.get();
}
}
std::ostream & operator<< (std::ostream & os, const HepRandom & dist) {
return dist.put(os);
......@@ -177,12 +276,12 @@ void HepRandom::setTheEngine (HepRandomEngine* theNewEngine)
void HepRandom::saveEngineStatus( const char filename[] )
{
theDefaults().theEngine->saveStatus( filename );
}
}
void HepRandom::restoreEngineStatus( const char filename[] )
{
theDefaults().theEngine->restoreStatus( filename );
}
}
std::ostream& HepRandom::saveFullState ( std::ostream & os ) {
os << *getTheEngine();
......@@ -205,7 +304,7 @@ std::istream& HepRandom::restoreStaticRandomStates ( std::istream & is ) {
void HepRandom::showEngineStatus()
{
theDefaults().theEngine->showStatus();
}
}
int HepRandom::createInstance()
{
......
......@@ -458,7 +458,7 @@ class poisson {
}
};
double* createRefDist ( poisson pdist, int N,
double* createRefDist ( poisson pdist, int N1,
int MINBIN, int MAXBINS, int clumping,
int& firstBin, int& lastBin ) {
......@@ -482,13 +482,13 @@ double* createRefDist ( poisson pdist, int N,
double binc;
while ( c < MAXBINS ) {
for ( ic=0, binc=0; ic < clumping; ic++, r++ ) {
binc += pdist(r) * N;
binc += pdist(r) * N1;
}
start += binc;
if (binc >= MINBIN) break;
c++;
if ( c > MAXBINS/3 ) {
cout << "The number of samples supplied " << N <<
cout << "The number of samples supplied " << N1 <<
" is too small to set up a chi^2 to test this distribution.\n";
exit(-1);
}
......@@ -501,7 +501,7 @@ double* createRefDist ( poisson pdist, int N,
double next = 0;
while ( c < MAXBINS ) {
for ( ic=0, binc=0; ic < clumping; ic++, r++ ) {
binc += pdist(r) * N;
binc += pdist(r) * N1;
}
next = binc;
if (next < MINBIN) break;
......@@ -514,7 +514,7 @@ double* createRefDist ( poisson pdist, int N,
next += refdist[lastBin];
while ( c < MAXBINS ) {
for ( ic=0, binc=0; ic < clumping; ic++, r++ ) {
binc += pdist(r) * N;
binc += pdist(r) * N1;
}
next += binc;
c++;
......@@ -526,12 +526,12 @@ double* createRefDist ( poisson pdist, int N,
} // createRefDist()
bool poissonTest ( RandPoisson & dist, double mu, int N ) {
bool poissonTest ( RandPoisson & dist, double mu, int N2 ) {
// Three tests will be done:
//
// A chi-squared test will be used to test the hypothesis that the
// generated distribution of N numbers matches the proper Poisson distribution.
// generated distribution of N2 numbers matches the proper Poisson distribution.
//
// The same test will be applied to the distribution of numbers "clumping"
// together std::sqrt(mu) bins. This will detect small deviations over several
......@@ -552,9 +552,9 @@ bool poissonTest ( RandPoisson & dist, double mu, int N ) {
poisson pdist(mu);
double* refdist = createRefDist( pdist, N,
double* refdist = createRefDist( pdist, N2,
MINBIN, MAXBINS, 1, firstBin, lastBin);
double* refdist2 = createRefDist( pdist, N,
double* refdist2 = createRefDist( pdist, N2,
MINBIN, MAXBINS, clumping, firstBin2, lastBin2);
// Now roll the random dists, treating the tails in the same way as we go.
......@@ -572,7 +572,7 @@ bool poissonTest ( RandPoisson & dist, double mu, int N ) {
int r1;
int r2;
for (int i = 0; i < N; i++) {
for (int i = 0; i < N2; i++) {
r = dist.fire();
sum += r;
moment += (r - mu)*(r - mu);
......@@ -641,11 +641,11 @@ bool poissonTest ( RandPoisson & dist, double mu, int N ) {
// Check out the mean and sigma to apply the third test
double mean = sum / N;
double sigma = std::sqrt( moment / (N-1) );
double mean = sum / N2;
double sigma = std::sqrt( moment / (N2-1) );
double deviationMean = std::fabs(mean - mu)/(std::sqrt(mu/N));
double expectedSigma2Variance = (2*N*mu*mu/(N-1) + mu) / N;
double deviationMean = std::fabs(mean - mu)/(std::sqrt(mu/N2));
double expectedSigma2Variance = (2*N2*mu*mu/(N2-1) + mu) / N2;
double deviationSigma = std::fabs(sigma*sigma-mu)/std::sqrt(expectedSigma2Variance);
cout << "Mean (should be " << mu << ") is " << mean << "\n";
......
......@@ -88,6 +88,7 @@ void testRandGauss(std::vector<double> const& reference, bool& result) {
// check the shoot method using the CLHEP thread local
// engine
CLHEP::HepJamesRandom engine2(seedL1);
CLHEP::HepRandomEngine* savedEngine = CLHEP::HepRandom::getTheEngine();
CLHEP::HepRandom::setTheEngine(&engine2);
// setFlag causes it to not use the cached value
// and generate a new pair of random numbers
......@@ -99,6 +100,7 @@ void testRandGauss(std::vector<double> const& reference, bool& result) {
reference[4] != CLHEP::RandGauss::shoot()) {
result = false;
}
CLHEP::HepRandom::setTheEngine(savedEngine);
}
#if defined __GNUC__
......
==============================
19.04.16 Release CLHEP-2.3.2.1
==============================
==============================
10.11.15 Release CLHEP-2.3.1.1
==============================
==============================
......
==============================
19.04.16 Release CLHEP-2.3.2.1
==============================
==============================
10.11.15 Release CLHEP-2.3.1.1
==============================
==============================
......
==============================
19.04.16 Release CLHEP-2.3.2.1
==============================
2016-03-25 W. David Dagenhart <wdd@fnal.gov>
* Utility/use_atomic.h: Use std::atomic when the compiler declares it
uses the C++11 standard
==============================
10.11.15 Release CLHEP-2.3.1.1
==============================
......
#ifndef CLHEP_USE_ATOMIC_GUARD_H
#define CLHEP_USE_ATOMIC_GUARD_H
// ======================================================================
//
// Use std::atomic when the compiler declares it uses the C++11 standard
//
// ======================================================================
#if __cplusplus >= 201103L
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 7)
#include <atomic>
#define CLHEP_USE_ATOMIC
#elif __clang__
#if __has_feature(c_atomic)
#include <atomic>
#define CLHEP_USE_ATOMIC
#endif
#endif
#endif
#endif
==============================
19.04.16 Release CLHEP-2.3.2.1
==============================
==============================
10.11.15 Release CLHEP-2.3.1.1
==============================
==============================
......
......@@ -40,6 +40,8 @@ macro( clhep_check_variable_names )
message( STATUS "clhep_check_variable_names: CMAKE_CXX_FLAGS_RELWITHDEBINFO is ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}" )
message( STATUS "clhep_check_variable_names: CMAKE_CXX_STANDARD_LIBRARIES is ${CMAKE_CXX_STANDARD_LIBRARIES}" )
message( STATUS "clhep_check_variable_names: CMAKE_CXX_LINK_FLAGS is ${CMAKE_CXX_LINK_FLAGS}" )
message( STATUS "clhep_check_variable_names: CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS is ${CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS}" )
message( STATUS "clhep_check_variable_names: CMAKE_SHARED_LINKER_FLAGS is ${CMAKE_SHARED_LINKER_FLAGS}" )
endmacro( clhep_check_variable_names )
macro( clhep_autoconf_variables )
......@@ -86,29 +88,10 @@ macro( clhep_autoconf_variables )
endmacro( clhep_autoconf_variables )
macro( _clhep_verify_cxx0x )
message( FATAL_ERROR "The c++0x extension is no longer supported. Please use c++11 or later.")
if( ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" )
if( CMAKE_CXX_COMPILER_VERSION VERSION_LESS 2.9 )
message( FATAL_ERROR "c++0x extension is not available for ${CMAKE_CXX_COMPILER_ID}${CMAKE_CXX_COMPILER_VERSION}")
else()
set( HAVE_STDCXX true )
endif()
elseif(CMAKE_COMPILER_IS_GNUCXX)
if( CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.3 )
message( FATAL_ERROR "c++0x extension is not available for ${CMAKE_CXX_COMPILER}")
else()
set( HAVE_STDCXX true )
endif()
else()
message(STATUS "clhep_set_compiler_flags: Do not know how to set c++11 extensions for ${CMAKE_CXX_COMPILER_ID}")
endif()
endmacro( _clhep_verify_cxx0x )
macro( _clhep_verify_cxx11 )
if( ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" )
if( CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.3 )
message( FATAL_ERROR "c++11 extension is not available for ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
if( CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5 )
message( FATAL_ERROR "CLHEP now requires c++11 support with clang 3.5 or later")
else()
set( HAVE_STDCXX true )
endif()
......@@ -119,10 +102,8 @@ macro( _clhep_verify_cxx11 )
set( HAVE_STDCXX true )
endif()
elseif(CMAKE_COMPILER_IS_GNUCXX)
if( CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7 )
message( FATAL_ERROR "c++11 extension is not available for ${CMAKE_CXX_COMPILER}")
elseif( CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8 )
message( FATAL_ERROR "CLHEP now requires gcc 4.8 or later")
if( CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8 )
message( FATAL_ERROR "CLHEP now requires c++11 support with gcc 4.8 or later")
else()
set( HAVE_STDCXX true )
endif()
......@@ -164,7 +145,7 @@ macro( _clhep_verify_cxx14 )
endif()
elseif( ${CMAKE_CXX_COMPILER_ID} STREQUAL "Intel" )
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0)
message( FATAL_ERROR "c++11 extension is not available for ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
message( FATAL_ERROR "c++14 extension is not available for ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
else()
set( HAVE_STDCXX true )
endif()
......@@ -206,67 +187,45 @@ macro( _clhep_check_cxxstd )
##message(STATUS "_clhep_check_cxxstd debug: CLHEP_BUILD_CXXSTD HAVE_STDCXX: ${CLHEP_BUILD_CXXSTD} ${HAVE_STDCXX}")
if( DEFINED HAVE_STDCXX )
if( ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" )
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CLHEP_BUILD_CXXSTD} -pthread" )
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CLHEP_BUILD_CXXSTD}" )
elseif( ${CMAKE_CXX_COMPILER_ID} STREQUAL "Intel" )
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CLHEP_BUILD_CXXSTD} -pthread" )
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CLHEP_BUILD_CXXSTD" )
elseif(CMAKE_COMPILER_IS_GNUCXX)