Commit 428bde89 authored by Praetorius, Simon's avatar Praetorius, Simon

Initial commit

parents
Pipeline #1596 failed with stages
in 9 seconds
build*/
CMakeCache.txt
CMakeFiles/
Makefile
\ No newline at end of file
# We require version CMake version 3.1 to prevent issues
# with dune_enable_all_packages and older CMake versions.
cmake_minimum_required(VERSION 3.1)
project(dune-common-extensions CXX)
if(NOT (dune-common_DIR OR dune-common_ROOT OR
"${CMAKE_PREFIX_PATH}" MATCHES ".*dune-common.*"))
string(REPLACE ${CMAKE_PROJECT_NAME} dune-common dune-common_DIR
${PROJECT_BINARY_DIR})
endif()
#find dune-common and set the module path
find_package(dune-common REQUIRED)
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules"
${dune-common_MODULE_PATH})
#include the dune macros
include(DuneMacros)
# start a dune project with information from dune.module
dune_project()
dune_enable_all_packages()
add_subdirectory(src)
add_subdirectory(dune)
add_subdirectory(doc)
add_subdirectory(cmake/modules)
# finalize the dune project, e.g. generating config.h etc.
finalize_dune_project(GENERATE_CONFIG_H_CMAKE)
Copyright holders:
2018 Simon Praetorius
The dune-common-extensions library, headers and test programs are copyrighted
free software. You can use, modify and/or redistribute it under the terms of
either one of the two following licenses:
* The GNU Lesser General Public License as published by the Free Software
Foundation, either Version 3 of the license or (at your option) any later
version. You can find a copy of the GNU Lesser General Public License, Version
3, in the files GPL-3 and LGPL-3 or at <http://www.gnu.org/licenses/lgpl-3.0>.
* Version 2 of the GNU General Public License as published by the Free Software
Foundation, with the following special exception for linking and compiling
against the dune-common-extensions library, the so-called "runtime exception":
As a special exception, you may use the dune-common-extensions source files
as part of a software library or application without restriction.
Specifically, if other files instantiate templates or use macros or inline
functions from one or more of the dune-common-extensions source files, or
you compile one or more of the dune-common-extensions source files and link
them with other files to produce an executable, this does not by itself
cause the resulting executable to be covered by the GNU General Public
License. This exception does not however invalidate any other reasons why
the executable file might be covered by the GNU General Public License.
This license is intended to be similar to the GNU Lesser General Public
License, Version 2, which by itself isn't suitable for a template library. You
can find a copy of the GNU General Public License, Version 2, in the file
GPL-2 or at <http://www.gnu.org/licenses/gpl-2.0>.
Preparing the Sources
=========================
Additional to the software mentioned in README you'll need the
following programs installed on your system:
cmake >= 3.1
Getting started
---------------
If these preliminaries are met, you should run
dunecontrol all
which will find all installed dune modules as well as all dune modules
(not installed) which sources reside in a subdirectory of the current
directory. Note that if dune is not installed properly you will either
have to add the directory where the dunecontrol script resides (probably
./dune-common/bin) to your path or specify the relative path of the script.
Most probably you'll have to provide additional information to dunecontrol
(e. g. compilers, configure options) and/or make options.
The most convenient way is to use options files in this case. The files
define four variables:
CMAKE_FLAGS flags passed to cmake (during configure)
An example options file might look like this:
#use this options to configure and make if no other options are given
CMAKE_FLAGS=" \
-DCMAKE_CXX_COMPILER=g++-6 \
-DCMAKE_CXX_FLAGS='-Wall -pedantic' \
-DCMAKE_INSTALL_PREFIX=/install/path" #Force g++-6 and set compiler flags
If you save this information into example.opts you can pass the opts file to
dunecontrol via the --opts option, e. g.
dunecontrol --opts=example.opts all
More info
---------
See
dunecontrol --help
for further options.
The full build system is described in the dune-common/doc/buildsystem (Git version) or under
share/doc/dune-common/buildsystem if you installed DUNE!
set(modules "DuneCommonExtensionsMacros.cmake")
install(FILES ${modules} DESTINATION ${DUNE_INSTALL_MODULEDIR})
# File for module specific CMake tests.
/* begin dune-common-extensions
put the definitions for config.h specific to
your project here. Everything above will be
overwritten
*/
/* begin private */
/* Name of package */
#define PACKAGE "@DUNE_MOD_NAME@"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "@DUNE_MAINTAINER@"
/* Define to the full name of this package. */
#define PACKAGE_NAME "@DUNE_MOD_NAME@"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "@DUNE_MOD_NAME@ @DUNE_MOD_VERSION@"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "@DUNE_MOD_NAME@"
/* Define to the home page for this package. */
#define PACKAGE_URL "@DUNE_MOD_URL@"
/* Define to the version of this package. */
#define PACKAGE_VERSION "@DUNE_MOD_VERSION@"
/* end private */
/* Define to the version of dune-common-extensions */
#define DUNE_COMMON_EXTENSIONS_VERSION "@DUNE_COMMON_EXTENSIONS_VERSION@"
/* Define to the major version of dune-common-extensions */
#define DUNE_COMMON_EXTENSIONS_VERSION_MAJOR @DUNE_COMMON_EXTENSIONS_VERSION_MAJOR@
/* Define to the minor version of dune-common-extensions */
#define DUNE_COMMON_EXTENSIONS_VERSION_MINOR @DUNE_COMMON_EXTENSIONS_VERSION_MINOR@
/* Define to the revision of dune-common-extensions */
#define DUNE_COMMON_EXTENSIONS_VERSION_REVISION @DUNE_COMMON_EXTENSIONS_VERSION_REVISION@
/* end dune-common-extensions
Everything below here will be overwritten
*/
add_subdirectory("doxygen")
# shortcut for creating the Doxyfile.in and Doxyfile
add_doxygen_target()
# This file contains local changes to the doxygen configuration
# please us '+=' to add file/directories to the lists
# The INPUT tag can be used to specify the files and/or directories that contain
# documented source files. You may enter file names like "myfile.cpp" or
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT += @top_srcdir@/dune/
# see e.g. dune-grid for the examples of mainpage and modules
# INPUT += @srcdir@/mainpage \
# @srcdir@/modules
# The EXCLUDE tag can be used to specify files and/or directories that should
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
# EXCLUDE += @top_srcdir@/dune/common-extensions/test
# The EXAMPLE_PATH tag can be used to specify one or more files or
# directories that contain example code fragments that are included (see
# the \include command).
# EXAMPLE_PATH += @top_srcdir@/src
# The IMAGE_PATH tag can be used to specify one or more files or
# directories that contain image that are included in the documentation (see
# the \image command).
# IMAGE_PATH += @top_srcdir@/dune/common-extensions/pics
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
CXX=@CXX@
CC=@CC@
DEPENDENCIES=@REQUIRES@
Name: @PACKAGE_NAME@
Version: @VERSION@
Description: Extensions to the dune-common module
URL: http://gitlab.mn.tu-dresden.de/spraetor/dune-common-extensions
Requires: dune-common
Libs: -L${libdir}
Cflags: -I${includedir}
################################
# Dune module information file #
################################
#Name of the module
Module: dune-common-extensions
Version: 0.1
Maintainer: simon.praetorius@tu-dresden.de
#depending on
Depends: dune-common
add_subdirectory(common)
add_subdirectory(std)
add_subdirectory(test)
\ No newline at end of file
#install headers
install(FILES
charconv.hh
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/common/std)
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_COMMON_STD_CHARCONV_HH
#define DUNE_COMMON_STD_CHARCONV_HH
/** \file
* \brief Implements a backport of c++17's to_chars and from_chars facilities for a locale-independent
* string to/from number conversion, respectively.
**/
#include <utility>
#ifdef __has_include
#if __has_include(<charconv>) && defined(__cpp_lib_to_chars) && !defined(DUNE_NO_STD_CHARCONV)
#define DUNE_HAVE_CHARCONV 1
#endif
#endif
#ifdef DUNE_HAVE_CHARCONV
#include <charconv>
#else
#include <algorithm>
#include <iomanip>
#include <ios>
#include <iterator>
#include <limits>
#include <locale>
#include <sstream>
#include <system_error>
#include <type_traits>
#include <utility>
#endif
namespace Dune
{
namespace Std
{
#ifdef DUNE_HAVE_CHARCONV
using chars_format = std::chars_format;
using from_chars_result = std::from_chars_result;
using std::from_chars;
using to_chars_result = std::to_chars_result;
using std::to_chars;
#else // DUNE_HAVE_CHARCONV
// A BitmaskType used to specify floating-point formatting for to_chars and from_chars
enum class chars_format : int
{
scientific = 1,
fixed = 2,
hex = 4,
general = fixed | scientific
};
struct from_chars_result
{
const char* ptr;
std::errc ec;
};
struct to_chars_result
{
char* ptr;
std::errc ec;
};
namespace Impl
{
template<typename T, typename StreamManipulator>
from_chars_result fromCharsImpl (const char* first, const char* last, T& value,
StreamManipulator manipulator)
{
std::istringstream s(std::string(first,last));
s.imbue(std::locale::classic()); // make sure we are in locale "C"
manipulator(s);
try {
s >> value; // extract value
} catch (...) {
s.setstate(std::ios_base::failbit);
}
if (s.fail()) {
if (value == std::numeric_limits<T>::max() || value == std::numeric_limits<T>::min())
// range error
return from_chars_result{first + s.tellg(), std::errc::result_out_of_range};
else
// extraction fails
return from_chars_result{first, std::errc::invalid_argument};
}
return from_chars_result{first + s.tellg(), std::errc{}};
}
template<typename T, typename StreamManipulator>
to_chars_result toCharsImpl (char* first, char* last, T value,
StreamManipulator manipulator)
{
std::ostringstream s;
s.imbue(std::locale::classic()); // make sure we are in locale "C"
manipulator(s);
// negative integer values in base != 10 are not correctly converted
bool sign = value < T(0);
try {
s << (sign ? -value : value);
} catch (...) {
s.setstate(std::ios_base::failbit);
}
if (s.fail())
return to_chars_result{last, std::errc::value_too_large};
auto str = (sign ? "-" : "") + s.str();
auto num = std::min(std::distance(first, last),
std::distance(str.begin(), str.end()));
std::copy_n(str.begin(), num, first);
return to_chars_result{first + num, std::errc{}};
}
} // end namespace Impl
/// \brief Converts a character sequence to an integer value
template<typename T,
std::enable_if_t<std::is_integral<T>::value, int> = 0>
from_chars_result from_chars (const char* first, const char* last, T& value, int base = 10)
{
return Impl::fromCharsImpl(first, last, value, [base](auto& s) { s >> std::setbase(base); });
}
/// \brief Converts a character sequence to a floating-point value
template<typename T,
std::enable_if_t<std::is_floating_point<T>::value, int> = 0>
from_chars_result from_chars (const char* first, const char* last, T& value,
chars_format fmt = chars_format::general)
{
return Impl::fromCharsImpl(first, last, value, [fmt](auto& s)
{
if ((int(fmt) & int(chars_format::scientific)) != 0)
s >> std::scientific;
if ((int(fmt) & int(chars_format::fixed)) != 0)
s >> std::fixed;
if ((int(fmt) & int(chars_format::hex)) != 0) {
s >> std::hexfloat;
DUNE_THROW(NotImplemented,
"Reading hexfloat values not supported by many standard libraries currently.");
}
});
}
/// \brief Converts an integer value to a character sequence
template <class T,
std::enable_if_t<std::is_integral<T>::value, int> = 0>
to_chars_result to_chars (char* first, char* last, T value, int base = 10)
{
return Impl::toCharsImpl(first, last, value, [base](auto& s) { s << std::setbase(base); });
}
/// \brief Converts a floating-point value to a character sequence
template <class T,
std::enable_if_t<std::is_floating_point<T>::value, int> = 0>
to_chars_result to_chars (char* first, char* last, T value)
{
return Impl::toCharsImpl(first, last, value, [](auto& /*s*/) {});
}
/// \brief Converts a floating-point value to a character sequence with additional format specifier
template <class T,
std::enable_if_t<std::is_floating_point<T>::value, int> = 0>
to_chars_result to_chars (char* first, char* last, T value, chars_format fmt)
{
return Impl::toCharsImpl(first, last, value, [fmt](auto& s)
{
if ((int(fmt) & int(chars_format::scientific)) != 0)
s << std::scientific;
if ((int(fmt) & int(chars_format::fixed)) != 0)
s << std::fixed;
if ((int(fmt) & int(chars_format::hex)) != 0)
s << std::hexfloat;
});
}
/// \brief Converts a floating-point value to a character sequence with format specifier and precision
template <class T,
std::enable_if_t<std::is_floating_point<T>::value, int> = 0>
to_chars_result to_chars (char* first, char* last, T value, chars_format fmt, int precision)
{
return Impl::toCharsImpl(first, last, value, [fmt,precision](auto& s)
{
s << std::setprecision(precision);
if ((int(fmt) & int(chars_format::scientific)) != 0)
s << std::scientific;
if ((int(fmt) & int(chars_format::fixed)) != 0)
s << std::fixed;
if ((int(fmt) & int(chars_format::hex)) != 0)
s << std::hexfloat;
});
}
#endif // DUNE_HAVE_CHARCONV
} // end namespace Std
} // end namespace Dune
#endif // DUNE_COMMON_STD_CHARCONV_HH
dune_add_test(SOURCES charconvtest.cc
LINK_LIBRARIES dunecommon
LABELS quick)
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <cassert>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <limits>
#include <random>
#include <sstream>
#include <tuple>
#include <type_traits>
#include <iomanip>
#include <utility>
#ifdef __has_include
#if __has_include(<charconv>) && defined(__cpp_lib_to_chars)
#define DUNE_HAVE_CXX17_CHARCONV 1
#endif
#endif
#ifdef DUNE_HAVE_CXX17_CHARCONV
#include <charconv>
#endif
#include <dune/common/classname.hh>
#include <dune/common/filledarray.hh>
#include <dune/common/hybridutilities.hh>
#include <dune/common/float_cmp.hh>
#define DUNE_NO_STD_CHARCONV
#include <dune/common/std/charconv.hh>
#include <dune/common/test/testsuite.hh>
using namespace Dune;
template <class T, class = void>
struct Distribution
{
using type = std::uniform_real_distribution<T>;
};
template <class T>
struct Distribution<T, std::enable_if_t<std::is_integral<T>::value>>
{
using type = std::uniform_int_distribution<T>;
};
// Random number generator used to generate test data
template <class T, class = void>
struct Generator
{
Generator(T lo = std::numeric_limits<T>::min(),
T hi = std::numeric_limits<T>::max())
: gen{}
, dis(lo, hi)
{}
T operator()()
{
return dis(gen);
}
std::mt19937 gen;
typename Distribution<T>::type dis;
};
template <class T>
struct Generator<T, std::enable_if_t<std::is_floating_point<T>::value>>
{
Generator(T lo = std::numeric_limits<short>::min(),
T hi = std::numeric_limits<short>::max())
: gen{}
, dis(lo, hi)
{}
T operator()()
{
return dis(gen);
}
std::mt19937 gen;
typename Distribution<T>::type dis;
};
// specialization for bool, since uniform_int_distribution not implemented for bool
template <>
struct Generator<bool,void>
{
using T = signed short;
Generator(T lo = std::numeric_limits<T>::min(),
T hi = std::numeric_limits<T>::max())
: gen{}
, dis(lo, hi)
{}
bool operator()()
{
return dis(gen) >= 0;
}
std::mt19937 gen;
typename Distribution<T>::type dis;
};
template <class T, class = void>
struct Comparator
{
bool operator()(T const& x, T const& y) { return Dune::FloatCmp::eq(x, y); }
};
template <class T>
struct Comparator<T, std::enable_if_t<std::is_integral<T>::value>>
{
bool operator()(T const& x, T const& y) { return x == y; }
};
int main()
{
std::srand(std::time(nullptr));
using IntegerTypes = std::tuple<bool, signed short, signed int, signed long, signed long long,
unsigned short, unsigned int, unsigned long, unsigned long long>;
using FloatingPointTypes = std::tuple<float, double, long double>;
TestSuite test;
Hybrid::forEach(IntegerTypes{}, [&test](auto value)
{
using namespace Dune;
using T = decltype(value);
std::cout << "test<" << className<T>() << ">...\n";
Generator<T> generate{};
for (int base : {8, 10, 16}) {
std::cout << " base(" << base << ")...\n";
for (int i = 0; i < 100; ++i) {
value = generate();
std::string buf(64, '\0');
char* bufPtr = &(buf[0]);
auto result1 = Std::to_chars(bufPtr, bufPtr + buf.size(), value, base);
T new_value;
auto result2 = Std::from_chars(bufPtr, result1.ptr, new_value, base);
// compare the result of to_chars with from_chars
test.check(bool(value == new_value), "integer equality");
// check the error codes
test.check(!std::make_error_code(result1.ec), "error code 1");
test.check(!std::make_error_code(result2.ec), "error code 2");
#ifdef DUNE_HAVE_CXX17_CHARCONV
std::cout << "Test c++17 from_chars\n";
T new_value2;
auto result3 = std::from_chars(bufPtr, result1.ptr, new_value2, base);
test.check(bool(new_value == new_value2), "comparison with std::from_chars");
#else
std::setlocale(LC_NUMERIC, "C");
T new_value2;
if (std::is_unsigned<T>::value)
new_value2 = std::strtoull(bufPtr, nullptr, base);
else
new_value2 = std::strtoll(bufPtr, nullptr, base);
test.check(bool(new_value == new_value2), "comparison with strTo<T>");
#endif
}
}
});
Hybrid::forEach(FloatingPointTypes{}, [&test](auto value)
{
using namespace Dune;
using T = decltype(value);
std::cout << "test<" << className<T>() << ">...\n";
Comparator<T> cmp{};
Generator<T> generate{};
for (Std::chars_format fmt : {Std::chars_format::scientific, Std::chars_format::fixed}) {
for (int i = 0; i < 100; ++i) {
value = generate();
std::string buf(64, '\0');
char* bufPtr = &(buf[0]);
auto result1 = Std::to_chars(bufPtr, bufPtr + buf.size(), value, fmt, std::numeric_limits<T>::digits10 + 3);
T new_value;
auto result2 = Std::from_chars(bufPtr, result1.ptr, new_value, fmt);
// compare the result of to_chars with from_chars
test.check(cmp(value, new_value), "floating point equality");
// check the error codes
test.check(!std::make_error_code(result1.ec), "error code 1");
test.check(!std::make_error_code(result2.ec), "error code 2");
#ifdef DUNE_HAVE_CXX17_CHARCONV
std::cout << "Test c++17 from_chars\n";
T new_value2;
auto result3 = std::from_chars(bufPtr, result1.ptr, new_value2, fmt);
test.check(cmp(new_value2, new_value), "comparison with std::from_chars");
#else
std::setlocale(LC_NUMERIC, "C");
T new_value2 = strtold(bufPtr, nullptr);
test.check(bool(new_value2 == new_value), "comparison with strTo<T>");
#endif
}
}
});
}
add_executable("dune-common-extensions" dune-common-extensions.cc)
target_link_dune_default_libraries("dune-common-extensions")
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <iostream>
#include <dune/common/parallel/mpihelper.hh> // An initializer of MPI
#include <dune/common/exceptions.hh> // We use exceptions
int main(int argc, char** argv)
{
try{
// Maybe initialize MPI
Dune::MPIHelper& helper = Dune::MPIHelper::instance(argc, argv);
std::cout << "Hello World! This is dune-common-extensions." << std::endl;
if(Dune::MPIHelper::isFake)
std::cout<< "This is a sequential program." << std::endl;
else
std::cout<<"I am rank "<<helper.rank()<<" of "<<helper.size()
<<" processes!"<<std::endl;
return 0;
}
catch (Dune::Exception &e){
std::cerr << "Dune reported error: " << e << std::endl;
}
catch (...){
std::cerr << "Unknown exception thrown!" << std::endl;
}
}