Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 31 additions & 32 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -205,51 +205,47 @@ endif()
# Do OSX checks
include(cmake/MacOSX.cmake)

# Check if we are using 2019 intel compilers or gcc 6.1 or 6.2 together with pybind11, and forbid the use of C++17 if so.
# Check if we are using 2019 intel compilers or gcc 6.1 or 6.2 together with pybind11, and forbid the use of C++17 or later if so.
set(PERMIT_CXX17_PLUS_CHECK TRUE)
if(HAVE_PYBIND11)
if(("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 18.0.6) OR
("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5.6 AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.3))
set(PERMIT_CXX17_CHECK FALSE)
else()
set(PERMIT_CXX17_CHECK TRUE)
set(PERMIT_CXX17_PLUS_CHECK FALSE)
endif()
endif()

# Prevent using C++17 if using gnu version 7.2
# Prevent using C++17 or later if using gnu version 7.2
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.1 AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.3)
set(PERMIT_CXX17_CHECK FALSE)
set(PERMIT_CXX17_PLUS_CHECK FALSE)
endif()

# Check for C++11, C++14 and C++17 support.
# GAMBIT requires at least C++17. Use the newest standard the compiler supports, up to C++23.
include(CheckCXXCompilerFlag)
if(PERMIT_CXX17_CHECK)
CHECK_CXX_COMPILER_FLAG("-std=c++17" COMPILER_SUPPORTS_CXX17)
if(PERMIT_CXX17_PLUS_CHECK)
CHECK_CXX_COMPILER_FLAG("-std=c++23" COMPILER_SUPPORTS_CXX23)
endif()
if(COMPILER_SUPPORTS_CXX17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
set(GAMBIT_SUPPORTS_CXX17 TRUE)
if(COMPILER_SUPPORTS_CXX23)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++23")
set(GAMBIT_SUPPORTS_CXX23 TRUE)
else()
if(PERMIT_CXX17_CHECK)
CHECK_CXX_COMPILER_FLAG("-std=c++1z" COMPILER_SUPPORTS_CXX1z)
if(PERMIT_CXX17_PLUS_CHECK)
CHECK_CXX_COMPILER_FLAG("-std=c++20" COMPILER_SUPPORTS_CXX20)
endif()
CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14)
if(COMPILER_SUPPORTS_CXX14)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
set(GAMBIT_SUPPORTS_CXX14 TRUE)
if(COMPILER_SUPPORTS_CXX20)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20")
set(GAMBIT_SUPPORTS_CXX20 TRUE)
else()
CHECK_CXX_COMPILER_FLAG("-std=c++1y" COMPILER_SUPPORTS_CXX1y)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(GAMBIT_SUPPORTS_CXX11 TRUE)
if(PERMIT_CXX17_PLUS_CHECK)
CHECK_CXX_COMPILER_FLAG("-std=c++17" COMPILER_SUPPORTS_CXX17)
endif()
if(COMPILER_SUPPORTS_CXX17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
set(GAMBIT_SUPPORTS_CXX17 TRUE)
else()
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
set(GAMBIT_SUPPORTS_CXX0X TRUE)
else()
message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()
message(FATAL_ERROR "${BoldRed}The compiler ${CMAKE_CXX_COMPILER} does not support C++17. GAMBIT requires a "
"compiler with at least C++17 support. Please use a newer compiler, or if a known "
"pybind11/compiler incompatibility is blocking the check above, retry with "
"-DWITH_PYBIND11=OFF.${ColourReset}")
endif()
endif()
endif()
Expand Down Expand Up @@ -321,12 +317,15 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STR
endif()

# Check for Eigen
find_package(Eigen3 3.1.0)
# Note: a minimum of 3.3.7 (rather than the older 3.1.0) is required because Eigen releases
# prior to that use several STL idioms (std::unary_function/std::binary_function, std::result_of,
# etc.) in their own headers that are deprecated or removed under C++17/C++20/C++23.
find_package(Eigen3 3.3.7)
if(EIGEN3_FOUND)
include_directories(SYSTEM "${EIGEN3_INCLUDE_DIR}")
message("-- Eigen version: ${EIGEN3_VERSION}")
else()
message("${BoldRed} Eigen v3.1.0 or greater not found. FlexibleSUSY and GM2Calc interfaces will be excluded.${ColourReset}")
message("${BoldRed} Eigen v3.3.7 or greater not found. FlexibleSUSY and GM2Calc interfaces will be excluded.${ColourReset}")
set(itch "${itch};gm2calc;flexiblesusy")
message(FATAL_ERROR "\nFlexibleSUSY is currently included in the GAMBIT distribution, so in fact it cannot be ditched. Please install Eigen3.\nIf Eigen3 is already installed in a non-standard location, you can point CMake to it by passing -DEIGEN3_INCLUDE_DIR=/path/to/eigen on the command line, or by setting the environment variable EIGEN3_ROOT (or EIGEN3_ROOT_DIR).\n(Note that this will change in future GAMBIT versions, where FlexibleSUSY will be a 'true' backend.)")
endif()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@ namespace Gambit
/// An exception for when Pythia fails to initialize.
class InitializationError : public std::exception
{
virtual const char* what() const throw()
virtual const char* what() const noexcept
{
return "Pythia could not initialize.";
}
};
/// An exception for when Pythia fails to generate events.
class EventGenerationError : public std::exception
{
virtual const char* what() const throw()
virtual const char* what() const noexcept
{
return "Pythia could not make the next event.";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ namespace Gambit
template <typename U>
static void run (U, hid_t &dataset_out, hid_t &dataset2_out, std::vector<hid_t> &datasets, std::vector<hid_t> &datasets2, const unsigned long long size, const std::unordered_map<PPIDpair, unsigned long long, PPIDHash, PPIDEqual>& RA_write_hash, const std::vector<std::vector <unsigned long long> > &pointid, const std::vector<std::vector <unsigned long long> > &rank, const std::vector<unsigned long long> &aux_sizes, hid_t &/*old_dataset*/, hid_t &/*old_dataset2*/)
{
std::vector<U> output(size, 0);
std::vector<U> output(size);
std::vector<int> valids(size, 0);

// Should no longer need the old datasets, they should have already been copied during "copy_hdf5"
Expand Down
16 changes: 8 additions & 8 deletions Utils/include/gambit/Utils/exceptions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ namespace Gambit
/// @}

/// Destructor
virtual ~exception() throw() {}
virtual ~exception() noexcept {}

/// Setter for the fatal flag.
void set_fatal(bool);

/// Retrieve the identity of the exception.
virtual const char* what() const throw();
virtual const char* what() const noexcept;

/// Raise the exception.
/// Log the exception and, if it is considered fatal, actually throw it.
Expand Down Expand Up @@ -199,10 +199,10 @@ namespace Gambit
special_exception(const char*);

/// Destructor
virtual ~special_exception() throw() {}
virtual ~special_exception() noexcept {}

/// Retrieve the identity of the exception.
virtual const char* what() const throw();
virtual const char* what() const noexcept;

/// Retrieve the message that this exception was raised with.
std::string message();
Expand Down Expand Up @@ -338,7 +338,7 @@ namespace Gambit
public:
SilentShutdownException();
SilentShutdownException(const std::string& message);
virtual const char* what() const throw();
virtual const char* what() const noexcept;
private:
std::string myWhat;
};
Expand All @@ -347,7 +347,7 @@ namespace Gambit
{
public:
SoftShutdownException(const std::string& message);
virtual const char* what() const throw();
virtual const char* what() const noexcept;
private:
std::string myWhat;
};
Expand All @@ -356,7 +356,7 @@ namespace Gambit
{
public:
HardShutdownException(const std::string& message);
virtual const char* what() const throw();
virtual const char* what() const noexcept;
private:
std::string myWhat;
};
Expand All @@ -365,7 +365,7 @@ namespace Gambit
{
public:
MPIShutdownException(const std::string& message);
virtual const char* what() const throw();
virtual const char* what() const noexcept;
private:
std::string myWhat;
};
Expand Down
2 changes: 1 addition & 1 deletion Utils/include/gambit/Utils/util_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ namespace Gambit
typedef calc_nElem<lims... > nElem;
T array[nElem::val];
Farray(){}
Farray(Farray<T,lims... > &in){*this = in;}
Farray(const Farray<T,lims... > &in){*this = in;}
template <typename ... Args>
typename enable_if_all_member<allowed_types, T&, Args...>::type::type
operator () (Args ... a)
Expand Down
12 changes: 6 additions & 6 deletions Utils/src/exceptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ namespace Gambit
}

/// Retrieve the identity of the exception.
const char* exception::what() const throw()
const char* exception::what() const noexcept
{
return myWhat.c_str();
}
Expand Down Expand Up @@ -365,7 +365,7 @@ namespace Gambit
special_exception::special_exception(const char* what) : myWhat(what), myMessage("") {}

/// Retrieve the identity of the exception.
const char* special_exception::what() const throw()
const char* special_exception::what() const noexcept
{
const char* temp;
temp = myWhat;
Expand Down Expand Up @@ -524,22 +524,22 @@ namespace Gambit
/// @{ SilentShutdownException member functions
SilentShutdownException::SilentShutdownException() {}
SilentShutdownException::SilentShutdownException(const std::string& message) : myWhat(message) {}
const char* SilentShutdownException::what() const throw() { return myWhat.c_str(); }
const char* SilentShutdownException::what() const noexcept { return myWhat.c_str(); }
/// @}

/// @{ SoftShutdownException member functions
SoftShutdownException::SoftShutdownException(const std::string& message) : myWhat(message) {}
const char* SoftShutdownException::what() const throw() { return myWhat.c_str(); }
const char* SoftShutdownException::what() const noexcept { return myWhat.c_str(); }
/// @}

/// @{ HardShutdownException member functions
HardShutdownException::HardShutdownException(const std::string& message) : myWhat(message) {}
const char* HardShutdownException::what() const throw() { return myWhat.c_str(); }
const char* HardShutdownException::what() const noexcept { return myWhat.c_str(); }
/// @}

/// @{ MPIShutdownException member functions
MPIShutdownException::MPIShutdownException(const std::string& message) : myWhat(message) {}
const char* MPIShutdownException::what() const throw() { return myWhat.c_str(); }
const char* MPIShutdownException::what() const noexcept { return myWhat.c_str(); }
/// @}

/// Global instance of piped invalid point class.
Expand Down
21 changes: 10 additions & 11 deletions cmake/backends.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -1716,10 +1716,9 @@ set(patch "${PROJECT_SOURCE_DIR}/Backends/patches/${name}/${ver}/patch_${name}")
# - Silence the deprecated-declarations warnings coming from Eigen3
set(GM2CALC_CXX_FLAGS "${BACKEND_CXX_FLAGS}")
set_compiler_warning("no-deprecated-declarations" GM2CALC_CXX_FLAGS)
# - gm2calc 1.2 depends on std::ptr_fun which is removed in c++17, so we need to fall back to c++14 (or c++11)
if(COMPILER_SUPPORTS_CXX17)
string(REGEX REPLACE "-std=c\\+\\+17" "-std=c++14" GM2CALC_CXX_FLAGS "${GM2CALC_CXX_FLAGS}")
endif()
# - gm2calc 1.2 depends on std::ptr_fun, which was removed in C++17, so we need to fall back to
# C++14 regardless of which (C++17 or later) standard GAMBIT itself is using.
string(REGEX REPLACE "-std=c\\+\\+(17|1z|20|2a|23|2b)" "-std=c++14" GM2CALC_CXX_FLAGS "${GM2CALC_CXX_FLAGS}")
set(GM2CALC_MAKESHAREDLIB "${CMAKE_CXX_COMPILER} ${CMAKE_SHARED_LINKER_FLAGS} ${NO_FIXUP_CHAINS} ${CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS}")
check_ditch_status(${name} ${ver} ${dir})
if(NOT ditched_${name}_${ver})
Expand Down Expand Up @@ -1747,10 +1746,9 @@ set(patch "${PROJECT_SOURCE_DIR}/Backends/patches/${name}/${ver}/patch_${name}")
# - Silence the deprecated-declarations warnings coming from Eigen3
set(GM2CALC_CXX_FLAGS "${BACKEND_CXX_FLAGS}")
set_compiler_warning("no-deprecated-declarations" GM2CALC_CXX_FLAGS)
# - gm2calc 1.3 depends on std::ptr_fun which is removed in c++17, so we need to fall back to c++14 (or c++11)
if(COMPILER_SUPPORTS_CXX17)
string(REGEX REPLACE "-std=c\\+\\+17" "-std=c++14" GM2CALC_CXX_FLAGS "${GM2CALC_CXX_FLAGS}")
endif()
# - gm2calc 1.3 depends on std::ptr_fun, which was removed in C++17, so we need to fall back to
# C++14 regardless of which (C++17 or later) standard GAMBIT itself is using.
string(REGEX REPLACE "-std=c\\+\\+(17|1z|20|2a|23|2b)" "-std=c++14" GM2CALC_CXX_FLAGS "${GM2CALC_CXX_FLAGS}")
set(GM2CALC_MAKESHAREDLIB "${CMAKE_CXX_COMPILER} ${CMAKE_SHARED_LINKER_FLAGS} ${NO_FIXUP_CHAINS} ${CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS}")
check_ditch_status(${name} ${ver} ${dir})
if(NOT ditched_${name}_${ver})
Expand Down Expand Up @@ -2102,9 +2100,10 @@ set(dir "${PROJECT_SOURCE_DIR}/Backends/installed/${name}/${ver}")
# OpenMP flags don't play nicely with clang and FastJet's antiquated libtoolized build system.
string(REGEX REPLACE "-Xclang -fopenmp" "" FJ_C_FLAGS "${BACKEND_C_FLAGS}")
string(REGEX REPLACE "-Xclang -fopenmp" "" FJ_CXX_FLAGS "${BACKEND_CXX_FLAGS}")
# FastJet 3.3.2 depends on std::auto_ptr which is removed in c++17, so we need to fall back to c++14 (or c++11)
string(REGEX REPLACE "-std=c\\+\\+17" "-std=c++14" FJ_CXX_FLAGS "${FJ_CXX_FLAGS}")
string(REGEX REPLACE "-std=c\\+\\+17" "-std=c++14" FJ_C_FLAGS "${FJ_C_FLAGS}")
# FastJet 3.3.2 depends on std::auto_ptr, which was removed in C++17, so we need to fall back to
# C++14 regardless of which (C++17 or later) standard GAMBIT itself is using.
string(REGEX REPLACE "-std=c\\+\\+(17|1z|20|2a|23|2b)" "-std=c++14" FJ_CXX_FLAGS "${FJ_CXX_FLAGS}")
string(REGEX REPLACE "-std=c\\+\\+(17|1z|20|2a|23|2b)" "-std=c++14" FJ_C_FLAGS "${FJ_C_FLAGS}")
set_compiler_warning("no-deprecated-declarations" FJ_CXX_FLAGS)
set_compiler_warning("no-deprecated-copy" FJ_CXX_FLAGS)
set(FJ_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${NO_FIXUP_CHAINS}")
Expand Down
9 changes: 6 additions & 3 deletions cmake/cmake_variables.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,15 @@
/// Name of the gambit executable
#define GAMBIT_EXECUTABLE "@PROJECT_NAME@"

/// Compiler supports C++14 features
#cmakedefine COMPILER_SUPPORTS_CXX14 1

/// Compiler supports C++17 features
#cmakedefine COMPILER_SUPPORTS_CXX17 1

/// Compiler supports C++20 features
#cmakedefine COMPILER_SUPPORTS_CXX20 1

/// Compiler supports C++23 features
#cmakedefine COMPILER_SUPPORTS_CXX23 1

/// Found link.h in system paths
#cmakedefine HAVE_LINK_H 1

Expand Down
3 changes: 0 additions & 3 deletions cmake/externals.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,6 @@ function(check_ditch_status name version dir)
set (itch "${itch}" "${name}_${version}")
elseif ((arg STREQUAL "x11") AND NOT X11_FOUND)
set (itch "${itch}" "${name}_${version}")
elseif ((arg STREQUAL "c++14") AND NOT GAMBIT_SUPPORTS_CXX14 AND NOT GAMBIT_SUPPORTS_CXX17)
message("${BoldCyan} X ${name} (${version}) needs c++14/17 but GAMBIT is compiled with a lower version. ${name} will be excluded.${ColourReset}")
set (itch "${itch}" "${name}_${version}")
elseif ((arg STREQUAL "rivet") AND ditched_rivet_${Rivet_ver})
set (itch "${itch}" "${name}_${version}")
endif()
Expand Down
12 changes: 9 additions & 3 deletions cmake/optional.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,14 @@ if(NOT LAPACK_LINKLIBS AND NOT LAPACK_FOUND)
endif()

# Helper function to check if ROOT has been compiled with the same standard as we are using here. If not, downgrade to the standard that ROOT was compiled with.
# Note: only C++17 and later are matched here, so a ROOT installation built with an older
# standard will not be matched and will trigger the "unable to detect" error below, prompting
# the user to rebuild ROOT with at least C++17.
function(check_root_std_flag)
# Loop over C++ standards
set(std_list "17;1z;14;1y;11;0x")
# Loop over C++ standards, newest first. "2b"/"2a"/"1z" are the pre-standardisation aliases
# that some compilers historically used for C++23/C++20/C++17 respectively, and are included
# here purely so that older ROOT builds using those flag spellings are still detected.
set(std_list "23;2b;20;2a;17;1z")
foreach(std ${std_list})
set(CXX_FLAG "-std=c++${std}")
set(CXX_FLAG_RE "-std=c\\+\\+${std}")
Expand Down Expand Up @@ -257,7 +262,8 @@ function(check_root_std_flag)
# Did we figure out the std used by ROOT?
if(NOT ROOT_USES_STD)
message(FATAL_ERROR "${BoldRed}Unable to detect what flavour of C++ your installation of ROOT has "
"been compiled with; please set -DWITH_ROOT=OFF.${ColourReset}")
"been compiled with, or it was compiled with an unsupported (pre-C++17) standard. "
"Please rebuild ROOT with at least C++17, or set -DWITH_ROOT=OFF.${ColourReset}")
endif()
# Check that the std used by ROOT is OK
CHECK_CXX_COMPILER_FLAG(${ROOT_CXX_FLAG} COMPILER_SUPPORTS_CXX${ROOT_STD})
Expand Down
6 changes: 0 additions & 6 deletions cmake/warnings.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,6 @@ set_compiler_warning("all" CMAKE_CXX_FLAGS)
set_compiler_warning("extra" CMAKE_CXX_FLAGS)
set_compiler_warning("no-misleading-indentation" CMAKE_CXX_FLAGS)

if(EIGEN3_FOUND AND EIGEN3_VERSION VERSION_LESS 3.3.0)
set_compiler_warning("no-ignored-attributes" CMAKE_CXX_FLAGS)
set_compiler_warning("no-deprecated-register" CMAKE_CXX_FLAGS)
set_compiler_warning("no-deprecated-declarations" CMAKE_CXX_FLAGS)
endif()

# set intel warnings
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
# "remark #981: operands are evaluated in unspecified order"
Expand Down
25 changes: 19 additions & 6 deletions contrib/fjcore-3.2.0/fjcore.cc
Original file line number Diff line number Diff line change
Expand Up @@ -726,15 +726,19 @@ FJCORE_END_NAMESPACE
FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
class ClosestPair2D : public ClosestPair2DBase {
public:
// GAMBIT: these constructors used to be defined inline here, but since Point is only
// forward-declared at this point in the class (and not fully defined until after
// ClosestPair2D's own class definition, below), their bodies -- which implicitly
// default-construct the std::vector<Point> _points member -- were being parsed in the
// "complete-class context" immediately after this class's closing brace, i.e. before
// Point was complete. Clang (unlike GCC) enforces this strictly under C++20/23, so the
// definitions are moved out-of-line, after Point is fully defined, matching the pattern
// already used below for _ID() and size().
ClosestPair2D(const std::vector<Coord2D> & positions,
const Coord2D & left_corner, const Coord2D & right_corner) {
_initialize(positions, left_corner, right_corner, positions.size());
};
const Coord2D & left_corner, const Coord2D & right_corner);
ClosestPair2D(const std::vector<Coord2D> & positions,
const Coord2D & left_corner, const Coord2D & right_corner,
const unsigned int max_size) {
_initialize(positions, left_corner, right_corner, max_size);
};
const unsigned int max_size);
void closest_pair(unsigned int & ID1, unsigned int & ID2,
double & distance2) const;
void remove(unsigned int ID);
Expand Down Expand Up @@ -809,6 +813,15 @@ inline bool floor_ln2_less(unsigned x, unsigned y) {
if (x>y) return false;
return (x < (x^y)); // beware of operator precedence...
}
inline ClosestPair2D::ClosestPair2D(const std::vector<Coord2D> & positions,
const Coord2D & left_corner, const Coord2D & right_corner) {
_initialize(positions, left_corner, right_corner, positions.size());
}
inline ClosestPair2D::ClosestPair2D(const std::vector<Coord2D> & positions,
const Coord2D & left_corner, const Coord2D & right_corner,
const unsigned int max_size) {
_initialize(positions, left_corner, right_corner, max_size);
}
inline int ClosestPair2D::_ID(const Point * point) const {
return point - &(_points[0]);
}
Expand Down
Loading