--- /dev/null
+Makefile
+Makefile.in
+config.guess
+config.h.in
+config.log
+config.status
+config.h
+config.lt
+config.sub
+configure
+configure
+aclocal.m4
+autom4te.cache
+depcomp
+install-sh
+missing
+mkinstalldirs
+libtool
+dune-common.pc
+semantic.cache
+configure.lineno
+stamp-h1
+dune-common-*.tar.gz
+dune-common-?.?
+ltmain.sh
+.libs/
+.deps/
+*.la
+*.o
+*.lo
+test-driver
+dependencies.m4
+dune.css
+build-cmake/
+*~
--- /dev/null
+# set up project
+project("dune-common" C CXX)
+
+# general stuff
+cmake_minimum_required(VERSION 2.8.6)
+
+# make sure our own modules are found
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/modules")
+
+# set the script dir for the macros.
+set(DUNE_COMMON_SCRIPT_DIR "${PROJECT_SOURCE_DIR}/cmake/scripts")
+
+#include the dune macros
+include(DuneMacros)
+
+# start a dune project with information from dune.module
+dune_project()
+
+# add subdirectories to execute CMakeLists.txt there
+add_subdirectory("lib")
+add_subdirectory("share")
+add_subdirectory("dune")
+add_subdirectory("bin")
+add_subdirectory("m4")
+add_subdirectory("am")
+add_subdirectory("doc")
+add_subdirectory("cmake/modules")
+add_subdirectory("cmake/scripts")
+
+# finalize the dune project, e.g. generating config.h etc.
+finalize_dune_project()
--- /dev/null
+Copyright holders:
+
+2003--2010 Peter Bastian
+2004--2013 Markus Blatt
+2013 Andreas Buhr
+2011--2013 Ansgar Burchardt
+2004--2005 Adrian Burri
+2006--2013 Andreas Dedner
+2003 Marc Droske
+2003--2013 Christian Engwer
+2004--2012 Jorrit Fahlke
+2008--2013 Bernd Flemisch
+2013 Christoph Gersbacher
+2005--2013 Carsten Gräser
+2010--2013 Christoph Grüninger
+2006 Bernhard Haasdonk
+2012--2013 Olaf Ippisch
+2013 Dominic Kempf
+2009 Leonard Kern
+2013 Torbjörn Klatt
+2003--2013 Robert Klöfkorn
+2005--2007 Sreejith Pulloor Kuttanikkad
+2012--2013 Arne Morten Kvarving
+2010--2013 Andreas Lauser
+2007--2011 Sven Marnach
+2012--2013 Tobias Malkmus
+2010 Rene Milk
+2011--2013 Steffen Müthing
+2003--2006 Thimo Neubauer
+2011 Rebecca Neumann
+2008--2013 Martin Nolte
+2004--2005 Mario Ohlberger
+2008--2013 Elias Pipping
+2011 Dan Popovic
+2009 Atgeirr Rasmussen
+2003--2013 Oliver Sander
+2006--2011 Uli Sack
+2006 Klaus Schneider
+2004 Roland Schulz
+2009--2012 BÃ¥rd Skaflestad
+2012 Matthias Wohlmuth
+2011 Jonathan Youett
+
+
+The DUNE library and headers are licensed under version 2 of the GNU
+General Public License (see below), with a special exception for
+linking and compiling against DUNE, the so-called "runtime exception."
+The license is intended to be similar to the GNU Lesser General
+Public License, which by itself isn't suitable for a template library.
+
+The exact wording of the exception reads as follows:
+
+ As a special exception, you may use the DUNE 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 source files, or you
+ compile one or more of the DUNE 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.
+
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
--- /dev/null
+Installation Instructions
+=========================
+
+For a full explanation of the DUNE installation process please read
+the installation notes [0]. The following introduction is meant for
+the impatient.
+
+Getting started
+---------------
+
+Suppose you have downloaded all DUNE modules of interest to your
+computer and extracted then in one common directory. See [1] for a
+list of available modules.
+
+To compile the modules Dune has to check several components of
+your system and whether prerequisites within the modules are met. For
+the ease of users we have designed a custom build system on top of the
+automake tools. Run
+
+ ./dune-common/bin/dunecontrol all
+
+to commence those tests and build all modules you have
+downloaded. Don't worry about messages telling you that libraries are
+missing: they are only needed for grid-self-checks we need for
+developing.
+
+You can customize the build to your specific needs by using an options file
+(see below)
+
+ ./dune-common/bin/dunecontrol --opts=/path_to/file.opts
+
+If you did not tell dunecontrol to install with an options file you
+need to run
+
+ ./dune-common/bin/dunecontrol make install
+
+to install Dune (you may need root-permissions for the install
+part depending on the prefix set)
+
+A more comprehensive introduction to the build system can be found in [2].
+
+Passing options to the build process
+------------------------------------
+
+Using the dunecontrol script the following atomic commands can be
+executed:
+
+- autogen (runs autogen in each module, only needed when downloaded
+ via svn)
+- configure (runs the configure tests for each module
+- exec (executes a command in each module directory)
+- make (runs make for each module)
+- update (updates the svn version)
+
+The composite command all simply runs autogen, configure and make for
+each module.
+
+As it is often not convenient (and for the target all impossible) to
+specify the options for each command as parameters after the call, one
+can pass the options via file specified by the --opts=<file>
+option. For each atomic command one specify the options via a ine
+
+<COMMANY_UPPERCASE>_FLAGS=<flags> # e.g.: MAKE_FLAGS=install
+
+The available options for make and svn are the natural ones. The
+configure commands available can be found by issuing
+
+dunecontrol --only=dune-common configure --help
+
+and for autogen by
+
+dunecontrol --only=dune-common autogen --help
+
+(In the svn version this has to be calles after running autogen.)
+
+
+An example of an options file is
+
+ # use a special compiler (g++ version 3.4) and install to a custom
+ # directory, default is /usr/local/bin
+ CONFIGURE_FLAGS="CXX=g++-3.4 --prefix='/tmp/Hu Hu'"
+ # Set the default target of make to install. Now the call above will
+ # not just build the DUNE modules but also install it
+ MAKE_FLAGS=install
+ # The default versions of automake and autogen are not sufficient
+ # therefore we need to specify what versions to use
+ AUTOGEN_FLAGS="--ac=2.59 --am=1.9
+
+Links
+-----
+
+0. http://www.dune-project.org/doc/installation-notes.html
+1. http://www.dune-project.org/download.html
+2. http://dune-project.org/doc/buildsystem/buildsystem.pdf
--- /dev/null
+# $Id$
+
+# we need the module file to be able to build via dunecontrol
+EXTRA_DIST= CMakeLists.txt dune.module
+
+# don't follow the full GNU-standard
+# we need automake 1.9 or newer
+AUTOMAKE_OPTIONS = foreign 1.9
+
+SUBDIRS = cmake dune lib share doc bin m4 am
+
+# use configured compiler for "make distcheck"
+DISTCHECK_CONFIGURE_FLAGS = CXX="$(CXX)" CC="$(CC)" --enable-parallel=@ENABLE_PARALLEL@ MPICC="$(MPICC)"
+
+include $(top_srcdir)/am/global-rules
+include $(top_srcdir)/am/top-rules
+
+# Distribute and install config.h.cmake
+configdir = $(datadir)/dune-common
+dist_config_DATA = config.h.cmake
+
+include $(top_srcdir)/am/cmake-pkg-config
--- /dev/null
+DUNE-library
+============
+
+DUNE, the Distributed and Unified Numerics Environment is a modular toolbox
+for solving partial differential equations with grid-based methods.
+
+The main intention is to create slim interfaces allowing an efficient use of
+legacy and/or new libraries. Using C++ techniques DUNE allows to use very
+different implementation of the same concept (i.e. grid, solver, ...) under
+a common interface with a very low overhead.
+
+DUNE was designed with flexibility in mind. It supports easy discretization
+using methods, like Finite Elements, Finite Volume and also Finite
+Differences. Through separation of data structures DUNE allows fast Linear
+Algebra like provided in the ISTL module, or usage of external libraries
+like blas.
+
+This package contains the basic DUNE common classes.
+
+Dependencies
+------------
+
+dune-common depends on the following software packages
+
+- pkg-config
+- icc (C/C++) >= 7.0 or GNU C, C++ >=3.4
+
+The following software is recommend but optional:
+
+- MPI (either OpenMPI, lam, or mpich suffice)
+
+For a full explanation of the DUNE installation process please read
+the installation notes [0]. The following introduction is meant for
+the impatient.
+
+License
+-------
+
+The DUNE-library and headers are licensed under version 2 of the GNU
+General Public License, with the so-called "runtime exception", as
+follows:
+
+ As a special exception, you may use the DUNE 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 source files, or you
+ compile one or more of the DUNE 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 licence clones the one of the libstc++ library. For further
+implications of this library please see their licence page [3]
+
+See the file COPYING for full copying permissions.
+
+Installation
+------------
+
+Short installation instructions can be found in file INSTALL. For the
+full instructions please see [0].
+
+Links
+-----
+
+0. http://www.dune-project.org/doc/installation-notes.html
+1. http://www.dune-project.org/download.html
+2. http://dune-project.org/doc/buildsystem/buildsystem.pdf
+3. http://gcc.gnu.org/onlinedocs/libstdc++/faq.html#faq.license
--- /dev/null
+Preparing the SVN-sources
+=========================
+
+Additional to the software mentioned in README you'll need the
+following programs installed on your system:
+
+ automake >= 1.9
+
+ autoconf >= 2.52
+
+ libtool
+
+For the documentation to build you'll need doxygen, wml, convert and latex
+installed.
+
+Dune also features a self-test. As some components (e.g. Albert,
+UG) depend on external libraries their self-tests will only run if
+those libraries are found. The paths to their installation prefix
+would then need to be passed via --with-...= parameters to configure.
+
+Important! If you don't want to develop Dune itself you won't need to
+provide external components! The Dune-library and -headers are
+independent of other libraries, instead the applications can choose
+which parts to use.
+
--- /dev/null
+Please see the Dune bugtracker at www.dune-project.org for things to do.
+
--- /dev/null
+Makefile
+Makefile.in
+semantic.cache
\ No newline at end of file
--- /dev/null
+install(PROGRAMS
+ checklog
+ cmake-pkg-config
+ documentation
+ doxygen
+ global-rules
+ headercheck
+ inkscape.am
+ latex
+ no-check-without-lib
+ sourcescheck
+ top-rules
+ webstuff
+ DESTINATION ${CMAKE_INSTALL_DATADIR}/dune-common/am
+)
--- /dev/null
+# $Id$
+
+am_DATA = inkscape.am webstuff global-rules sourcescheck \
+ no-check-without-lib latex checklog doxygen top-rules \
+ headercheck documentation cmake-pkg-config
+
+# Not all file names seem to be treated equal by _DATA.
+# inkscape.am no-check-without-lib have to be listed in
+# EXTRA_DIST to be included into the tarball.
+EXTRA_DIST = CMakeLists.txt inkscape.am no-check-without-lib
+amdir = $(datadir)/dune-common/am
+
+include $(top_srcdir)/am/global-rules
--- /dev/null
+# -*- Makefile -*-
+# $Id$
+
+#
+# check-log
+#
+# This file implements the build-rules needed by the automated tests.
+# "make check-log" will build the whole package and run all tests. For
+# each test a log file under $(topsrc_dir)/check-log is created which
+# contains the name of the test and what kind of test it was (build,
+# lib, run, ...). If a test fails this is logged, but all other tests
+# are still run.
+#
+# make OPTIONS:
+# LOG_TIMING - specific command to measure the time needed for each test
+# example: "make LOG_TIMING='time -p' check-log"
+#
+# IMPLEMENTATION: check-log depends on different targets for different
+# kinds of tests. These can run idividually by calling check-log-XXX.
+# Possible variants are (in order of dependence)
+# - libs (build all libraries)
+# - build (build all applications and tests)
+# - test (run each test from $(TESTS))
+# - sources (run sourcescheck in each directory)
+# - headers (run headercheck for each header)
+# - dir (create dir entries for database, no actual tests are run)
+#
+
+LOG_FILE = $(top_srcdir)/check-log.log
+LOG_DIR = $(top_srcdir)/check-log
+LOG_STORE = $(SHELL) $(DUNE_COMMON_ROOT)/bin/check-log-store $(LOG_FILE) $(LOG_DIR)
+LOG_TIMING =
+LOG_SET_OPTIONS = \
+ path=`test "$(subdir)" = "." && \
+ echo "/@PACKAGE_NAME@" || echo "/@PACKAGE_NAME@/$(subdir)"`; \
+ ppath=`dirname $$path`; \
+ dir=`basename $$path`
+
+$(DUNE_COMMON_ROOT)/bin/check-log-store: $(DUNE_COMMON_ROOT)/bin/check-log-store.in
+ cd $(DUNE_COMMON_ROOT)/bin/ && $(MAKE) check-log-store
+
+check-log: $(DUNE_COMMON_ROOT)/bin/check-log-store
+check-log:
+ rm -f $(LOG_FILE)
+
+check-log: check-log-libs
+check-log: check-log-build
+check-log: check-log-test
+check-log: check-log-sources
+check-log: check-log-headers
+check-log: check-log-dir
+
+check-log-libs: check-log-libs-recursive
+check-log-build: check-log-build-recursive
+check-log-test: check-log-test-recursive
+check-log-sources: check-log-sources-recursive
+check-log-headers: check-log-headers-recursive
+check-log-dir: check-log-dir-recursive
+
+check-log-headers-am:
+ $(LOG_SET_OPTIONS); \
+ list=`echo $(headercheck_PATTERN)`; \
+ test "$$list" != "$(headercheck_PATTERN)" || exit 0; \
+ for f in $$list; do \
+ echo "$(headercheck_IGNORE)" | tr ' ' '\n' | grep -q "$$f"; \
+ if echo "$(headercheck_IGNORE)" | tr ' ' '\n' | grep -q "$$f"; then continue; fi; \
+ $(LOG_TIMING) ($(MAKE) headercheck-am SILENT=0 HEADER=$$f; \
+ $(MAKE) headercheck-am SILENT=0 HEADER=$$f NO_CONFIG_H=1) > $(LOG_FILE) 2>&1; \
+ $(LOG_STORE) "headercheck" "$$f" "$$path"; \
+ done
+
+check-log-sources-am:
+ $(LOG_SET_OPTIONS); \
+ $(LOG_TIMING) $(MAKE) sourcescheck-am > $(LOG_FILE) 2>&1; \
+ $(LOG_STORE) "sources" "Makefile.am" "$$path"
+
+check-log-libs-am:
+ $(LOG_SET_OPTIONS); \
+ for lib in $(LTLIBRARIES); do \
+ $(LOG_TIMING) ($(MAKE) $$lib) > $(LOG_FILE) 2>&1; \
+ $(LOG_STORE) "lib" "$$lib" "$$path"; \
+ done;
+
+check-log-build-am:
+ $(LOG_SET_OPTIONS); \
+ for target in $(check_PROGRAMS) $(PROGRAMS); do \
+ $(LOG_TIMING) ($(MAKE) $$target) > $(LOG_FILE) 2>&1; \
+ $(LOG_STORE) "build" "$$target" "$$path"; \
+ done;
+
+check-log-test-am:
+ @LOG () { \
+ echo "$$1" > $(LOG_FILE).2; \
+ cat $(LOG_FILE) >> $(LOG_FILE).2; \
+ mv $(LOG_FILE).2 $(LOG_FILE); \
+ }; \
+ $(LOG_SET_OPTIONS); \
+ for tst in $(TESTS); do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ echo "TEST $${dir}$$tst"; \
+ if $(LOG_TIMING) $(TESTS_ENVIRONMENT) $${dir}$$tst > $(LOG_FILE) 2>&1; then \
+ case " $(XFAIL_TESTS) " in \
+ *" $$tst "*) \
+ LOG "ERROR: XPASS ($$tst)"; \
+ $(LOG_STORE) "run" "$$tst" "$$path" 1 0; \
+ ;; \
+ *) \
+ LOG "SUCCESS: PASS ($$tst)"; \
+ $(LOG_STORE) "run" "$$tst" "$$path" 0 0; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ case " $(XFAIL_TESTS) " in \
+ *" $$tst "*) \
+ LOG "SUCCESS: XFAIL ($$tst)"; \
+ $(LOG_STORE) "run" "$$tst" "$$path" 0 0; \
+ ;; \
+ *) \
+ LOG "ERROR: FAIL ($$tst)"; \
+ $(LOG_STORE) "run" "$$tst" "$$path" 1 0; \
+ ;; \
+ esac; \
+ else \
+ LOG "WARNING: SKIP ($$tst)"; \
+ $(LOG_STORE) "run" "$$tst" "$$path" 0 1; \
+ fi; \
+ done;
+
+check-log-dir-am:
+ $(LOG_SET_OPTIONS); \
+ $(LOG_STORE) "dir" "$$dir" "$$ppath"
+
+check-log-libs-recursive \
+check-log-build-recursive \
+check-log-test-recursive \
+check-log-sources-recursive \
+check-log-headers-recursive \
+check-log-dir-recursive:
+ @set fnord $$MAKEFLAGS; amf=$$2; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+.PHONY: check-log \
+ check-log-lib check-log-lib-am check-log-lib-recursive \
+ check-log-build check-log-build-am check-log-build-recursive \
+ check-log-test check-log-test-am check-log-test-recursive \
+ check-log-sources check-log-sources-am check-log-sources-recursive \
+ check-log-dir check-log-dir-am check-log-dir-recursive
--- /dev/null
+install-exec-local:
+ echo "set($(PACKAGE)_PREFIX \"$(prefix)\")" > $(PACKAGE)-config.tmp; \
+ echo "set($(PACKAGE)_INCLUDE_DIRS \"$(includedir)\")" >> $(PACKAGE)-config.tmp; \
+ if test -d $(top_srcdir)/cmake/scripts; then \
+ echo "set($(PACKAGE)_SCRIPT_DIR \"$(datadir)/dune/cmake/scripts\")" >> $(PACKAGE)-config.tmp; \
+ fi; \
+ if test "$(PACKAGE)" = "dune-common"; then \
+ echo "set(DOXYSTYLE_FILE \"$(datadir)/dune-common/doc/doxygen/Doxystyle\")" >> $(PACKAGE)-config.tmp; \
+ fi; \
+ if test -d $(top_srcdir)/cmake/modules; then \
+ echo "set($(PACKAGE)_MODULE_PATH \"$(datadir)/dune/cmake/modules\")" >> $(PACKAGE)-config.tmp; \
+ fi; \
+ echo "#set($(PACKAGE)_FAKE_CMAKE_PKGCONFIG TRUE)">> $(PACKAGE)-config.tmp; \
+ lib=`echo $(PACKAGE) | $(SED) 's/-//g'`; \
+ for suffix in .a .so; do \
+ if test -f $(DESTDIR)$(libdir)/lib$$lib$$suffix; then \
+ echo "set($(PACKAGE)_LIBRARIES \"$$lib\")">> $(PACKAGE)-config.tmp; \
+ if test "$$suffix" = ".a"; then \
+ static="STATIC"; \
+ fi; \
+ echo "add_library($$lib $$static IMPORTED)" >> $(PACKAGE)-config.tmp; \
+ echo "set_property(TARGET $$lib APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG)" >> $(PACKAGE)-config.tmp; \
+ echo "set_target_properties($$lib PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_NOCONFIG \"CXX\" IMPORTED_LOCATION_NOCONFIG $(libdir)/lib$$lib$$suffix)" >> $(PACKAGE)-config.tmp; \
+ break; \
+ fi; \
+ done; \
+ $(mkinstalldirs) $(DESTDIR)$(libdir)/cmake/$(PACKAGE) || exit 1; \
+ $(INSTALL_DATA) $(PACKAGE)-config.tmp $(DESTDIR)$(libdir)/cmake/$(PACKAGE)/$(PACKAGE)-config.cmake; \
+ rm $(PACKAGE)-config.tmp; \
+ full_version="$(DUNE_MOD_VERSION_MAJOR)"."$(DUNE_MOD_VERSION_MINOR)"."$(DUNE_MOD_VERSION_REVISION)"; \
+ echo "set(PACKAGE_VERSION \"$$full_version\")" >$(PACKAGE)-config-version.tmp; \
+ echo >>$(PACKAGE)-config-version.tmp; \
+ echo "if(\"\$${PACKAGE_FIND_VERSION_MAJOR}\" EQUAL \"$(DUNE_MOD_VERSION_MAJOR)\"" >> $(PACKAGE)-config-version.tmp; \
+ echo " AND \"\$${PACKAGE_FIND_VERSION_MINOR}\" EQUAL \"$(DUNE_MOD_VERSION_MINOR)\")">>$(PACKAGE)-config-version.tmp; \
+ echo " set (PACKAGE_VERSION_COMPATIBLE 1)" >>$(PACKAGE)-config-version.tmp; \
+ echo " if (\"\$${PACKAGE_FIND_VERSION}\" VERSION_EQUAL \"$$full_version\")" >> $(PACKAGE)-config-version.tmp; \
+ echo " set(PACKAGE_VERSION_EXACT 1)" >> $(PACKAGE)-config-version.tmp; \
+ echo " endif()" >> $(PACKAGE)-config-version.tmp; \
+ echo "endif()" >> $(PACKAGE)-config-version.tmp; \
+ $(INSTALL_DATA) $(PACKAGE)-config-version.tmp $(DESTDIR)$(libdir)/cmake/$(PACKAGE)/$(PACKAGE)-config-version.cmake; \
+ rm $(PACKAGE)-config-version.tmp
+
+
--- /dev/null
+# -*- Makefile -*-
+# $Id: global-rules 5267 2008-09-10 10:45:42Z christi $
+
+maintainer-clean-local: doc-clean-am
+
+###
+# build doc / web-install recursively
+doc-clean-am: clean-am doc-clean-documentation doc-clean-local
+doc-am: doc-all-documentation doc-local
+web-install-am: web-install-local
+
+doc-local:
+doc-clean-local:
+web-install-local:
+
+web-install: web-install-recursive
+doc: doc-recursive
+doc-clean: doc-clean-recursive
+
+web-install-recursive \
+doc-clean-recursive \
+doc-recursive:
+ @set fnord $$MAKEFLAGS; amf=$$2; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $(subdir)/$$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+install-data-local: install-documentation
+uninstall-local: uninstall-documentation
+
+####
+# "implementations"
+
+doc-all-documentation: $(DOCFILES)
+
+doc-clean-documentation:
+ -test -z "$(DOCFILES)" || rm -f $(DOCFILES)
+
+install-documentation: $(DOCFILES) install-documentation-local
+ @$(NORMAL_INSTALL)
+ test -z "$(docdir)" || $(MKDIR_P) "$(DESTDIR)$(docdir)"
+ @list='$(DOCFILES) $(DOCFILES_EXTRA)'; test -n "$(docdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \
+ done
+
+uninstall-documentation: uninstall-documentation-local
+ @$(NORMAL_UNINSTALL)
+ @list='$(DOCFILES) $(DOCFILES_EXTRA)'; test -n "$(docdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(docdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(docdir)" && rm -f $$files
+
+.PHONY: uninstall-documentation uninstall-documentation-local \
+ install-documentation install-documentation-local \
+ doc-clean-am doc-am web-install-am \
+ doc-local doc-clean-local web-install-local \
+ web-install doc doc-clean \
+ web-install-recursive doc-clean-recursive doc-recursive
--- /dev/null
+# -*-makefile-automake-*-
+
+doxygendir = $(docdir)/doxygen
+
+####
+# doxygen style files
+if DUNEWEB
+if WML
+
+DUNEWEBDOXY = @DUNEWEBDIR@/doc/doxygen
+# themeing doxygen
+DOXYGENHEADER = doxy-header.html
+DOXYGENFOOTER = doxy-footer.html
+
+doxy-header.html: BASEDIR=../../..
+doxy-footer.html: BASEDIR=../../..
+doxy-header.html: WMLOPTS=
+doxy-footer.html: WMLOPTS=
+
+doxy-header.html: @DUNEWEBDIR@/doc/doxygen/doxy-header.wml
+ $(WMLCMD) -I @DUNEWEBDIR@/doc/doxygen/ @DUNEWEBDIR@/doc/doxygen/doxy-header.wml -o $(abs_builddir)/doxy-header.html
+
+doxy-footer.html: @DUNEWEBDIR@/doc/doxygen/doxy-footer.wml
+ $(WMLCMD) -I @DUNEWEBDIR@/doc/doxygen/ @DUNEWEBDIR@/doc/doxygen/doxy-footer.wml -o $(abs_builddir)/doxy-footer.html
+
+endif # WML
+endif # DUNEWEB
+
+####
+# how to build doxygen documentation
+
+# EXTRAINSTALL in the html subdirectory
+DOXYGENHTMLFILES = *.html *.css *.png *.gif
+DOXYGENINSTALL = $(DOXYGENHTMLFILES) ../doxygen.log ../doxyerr.log
+
+if DOXYGEN
+if BUILD_DOCS
+ # disable dependency tracking when working without doxygen/documentation
+ DOXYGENTAG = doxygen-tag
+endif # BUILD_DOCS
+
+DUNEDOXYNIZE=@DUNE_COMMON_ROOT@/bin/dunedoxynize
+$(srcdir)/Doxyfile.in: FORCE
+ if test -f $(srcdir)/Doxylocal && test $(srcdir)/Doxylocal -nt $(srcdir)/Doxyfile.in; then \
+ cd $(top_srcdir) && $(DUNEDOXYNIZE); \
+ fi
+
+# build doxygen when 'make doc' is called
+# what files does the doxygen-generated stuff depend on (find-syntax)
+DOXYGEN_DEPENDON = -name \*.cc -o -name \*.hh -o -name \*.png -o -name modules
+# check dependency ourself to be robust
+$(DOXYGENTAG): FORCE Doxyfile $(DOXYGENHEADER) $(DOXYGENFOOTER)
+ set -e; \
+ DTAG=$(DOXYGENTAG); \
+ if test -f $(srcdir)/$(DOXYGENTAG); then DTAG=$(srcdir)/$(DOXYGENTAG); fi; \
+ if ! test -e "$$DTAG" || \
+ test x"`find $(top_srcdir) \( $(DOXYGEN_DEPENDON) \) -a -newer $$DTAG -print | grep -v cmake/modules`" != x; \
+ then \
+ echo Running doxygen. This may take a while... ; \
+ $(DOXYGEN) Doxyfile > doxygen.log <&-; \
+ if test "$$DOXYQUIET" != "1" && test -f doxyerr.log; \
+ then cat doxyerr.log; fi; \
+ if test -x "$(DUNEWEBDOXY)/update-doxygen.css"; \
+ then $(DUNEWEBDOXY)/update-doxygen.css $(abs_builddir)/html; fi; \
+ touch $(DOXYGENTAG) ; \
+ fi
+doc-doxygen: $(DOXYGENTAG) $(DOXYGENHEADER) $(DOXYGENFOOTER)
+else
+doc-doxygen:
+endif # DOXYGEN
+doc-local: doc-doxygen
+
+doxygen-html-install:
+ set -e; \
+ OLDPWD=$$PWD; \
+ dir=$(abs_srcdir); \
+ if test -f $(abs_builddir)/$(DOXYGENTAG); then dir=$(abs_builddir); fi; \
+ cd "$$dir/html/"; \
+ list=`echo $(DOXYGENHTMLFILES)`; \
+ cd "$$OLDPWD"; \
+ for p in $$list; do \
+ if test -f "$$dir/html/$$p"; then $(instcmd) $$dir/html/$$p $(instdir); fi; \
+ done;
+
+####
+# how to store doxygen in the tarball
+if BUILD_DOCS
+if DOXYGEN
+doxygen-dist-install: $(DOXYGENTAG)
+ set -e; mkdir $(distdir)/html; \
+ $(MAKE) doxygen-html-install instcmd="cp -fp" instdir="$(distdir)/html"
+ set -e; dir=$(abs_srcdir); \
+ if test -f $(abs_builddir)/$(DOXYGENTAG); then dir=$(abs_builddir); fi; \
+ cp $$dir/$(DOXYGENTAG) $(distdir)/$(DOXYGENTAG)
+
+dist-hook: doxygen-dist-install
+
+####
+# how to install doxygen
+
+install-doxygen: $(DOXYGENTAG)
+ set -e; $(mkinstalldirs) $(DESTDIR)/$(doxygendir); \
+ pwd; \
+ $(MAKE) doxygen-html-install instcmd="$(install_sh_DATA)" instdir="$(DESTDIR)/$(doxygendir)"
+
+uninstall-doxygen:
+ rm -rf $(DESTDIR)/$(doxygendir)
+
+# add doxygen to documentation-installation
+install-documentation-local: install-doxygen
+uninstall-documentation-local: uninstall-doxygen
+
+endif # DOXYGEN
+endif # BUILD_DOCS
+
+####
+# howto install doxygen in the web page
+include $(top_srcdir)/am/webstuff
+if DUNEWEB
+# how to install the doxygen documentation for the web site
+web-install-doxygen:
+ if test -d $(DUNEWEBDIR) && test -r $(DUNEWEBDIR)/Make.global ; then \
+ pushd html; \
+ $(MAKE) -f $(DUNEWEBDIR)/Make.global \
+ EXTRAINSTALL="$(DOXYGENINSTALL)" CURDIR="$(CURDIR)/@DUNE_MOD_NAME@-html" install ; \
+ popd; \
+ fi
+else
+web-install-doxygen:
+endif # DUNEWEB
+web-install-local: web-install-doxygen
+
+####
+# how to clean the doxygen stuff
+doc-clean-local: doxygen-doc-clean
+dist-clean-local: doxygen-dist-clean
+
+doxygen-dist-clean:
+ rm -f doxygen.log doxyerr.log $(DOXYGENTAG)
+
+doxygen-doc-clean:
+ rm -rf html $(DOXYGENTAG) $(DOXYGENHEADER) $(DOXYGENFOOTER) *~
+ rm -f doxyerr.log doxygen.log
+ test ! -f Doxylocal || rm -f Doxygen.in
+
+# nice trick from the GNU make infopage to force a rule to run
+FORCE:
--- /dev/null
+# -*- Makefile -*-
+# $Id$
+
+#
+# this file should be included into any Makefile.am so that we can
+# easily introduce new global rules. DO NOT OVERUSE!
+#
+
+# add "sourcescheck"-target testing if all source files are mentioned
+include $(top_srcdir)/am/sourcescheck
+
+# check consistency of the headers (see FS#394)
+include $(top_srcdir)/am/headercheck
+
+# add "check-log"-target to create automated build logs
+include $(top_srcdir)/am/checklog
+
+# add "doc"-target to create and clean documentation
+include $(top_srcdir)/am/documentation
--- /dev/null
+# -*- Makefile -*-
+# $Id: sourcescheck 5183 2008-04-27 17:37:08Z christi $
+
+headercheck_PATTERN = *.hh
+
+# set
+# headercheck_IGNORE = foo.hh
+# to ignore foo.hh
+
+hctest.o: hctest.cc
+ $(CXX) -I$(top_builddir) -I$(top_srcdir) -DHEADERCHECK \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) \
+ $(DUNEMPICPPFLAGS) $(ALL_PKG_CPPFLAGS) -c -o $@ $<
+
+headercheck:
+ @if test "x$V" = "x"; then \
+ SILENTSTR='V=$(AM_DEFAULT_VERBOSITY)' ; \
+ fi; \
+ if test "x$SILENT" = "x1"; then \
+ SILENTSTR='V=0' ; \
+ fi; \
+ if test "x$SILENT" = "x0"; then \
+ SILENTSTR='V=1' ; \
+ fi; \
+ if test x"$$HEADER" = "x"; then \
+ $(MAKE) $$SILENTSTR $(AM_MAKEFLAGS) headercheck-recursive; \
+ else \
+ $(MAKE) $$SILENTSTR $(AM_MAKEFLAGS) headercheck-am; \
+ fi
+
+headercheck-am:
+ @if test x"$$HEADER" != "x"; then \
+ list="$$HEADER"; \
+ else \
+ pushd "$(srcdir)" > /dev/null; \
+ list=`echo $(headercheck_PATTERN)`; \
+ popd > /dev/null; \
+ fi; \
+ test -z "$$NO_CONFIG_H" && NO_CONFIG_H=0; \
+ test "$$list" != "$(headercheck_PATTERN)" || exit 0; \
+ for f in $$list; do \
+ echo "$(headercheck_IGNORE)" | tr ' ' '\n' | grep -q "$$f"; \
+ if echo "$(headercheck_IGNORE)" | tr ' ' '\n' | grep -q "$$f"; then continue; fi; \
+ HEADER="$(subdir)/$$f"; \
+ echo "checking $$HEADER"; \
+ CCFILE=hctest.cc; \
+ OFILE=hctest.o; \
+ LOGFILE=hctest.log; \
+ rm -f $$CCFILE; \
+ test $$NO_CONFIG_H -ne 0 && echo " without config.h" \
+ || echo "#include <config.h>" > $$CCFILE; \
+ echo "#include <$${HEADER}>" >> $$CCFILE; \
+ echo "#include <$${HEADER}>" >> $$CCFILE; \
+ echo "int main () { return 0; }" >> $$CCFILE; \
+ make $$OFILE > $$LOGFILE 2>&1; \
+ SUCCESS=$$?; \
+ if ! (test $$SUCCESS -eq 0 && test -e $$OFILE); then \
+ echo "Error in $$HEADER"; \
+ test $V -ne 1 && echo "run with V=1 to show details" || cat $$LOGFILE; \
+ fi; \
+ warnings=`grep 'warning' $$LOGFILE`; \
+ FOUNDWARNINGS=$$?; \
+ if ( test $$FOUNDWARNINGS -eq 0 && test -e $$OFILE ); then \
+ echo "Warnings in $$HEADER"; \
+ test $V -ne 1 && echo "run with V=1 to show details" || cat $$LOGFILE; \
+ fi; \
+ rm -f $$OFILE; \
+ rm -f $$CCFILE; \
+ rm -f $$LOGFILE; \
+ test $$SUCCESS -eq 0 || exit $$SUCCESS; \
+ done
+
+headercheck-recursive:
+ @set fnord $$MAKEFLAGS; amf=$$2; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $(subdir)/$$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+.PHONY: headercheck headercheck-recursive headercheck-am
+
+# vim:set filetype=automake:
--- /dev/null
+if INKSCAPE
+.svg.png:
+ $(INKSCAPE) -e $@ $<
+endif INKSCAPE
--- /dev/null
+# -*- makefile -*-
+# $Id$
+
+# Rules for latex stuff
+
+# rerun TEX if log-file suggests that
+.tex.dvi:
+ export TEXINPUTS=.:$(abs_builddir):${TEXINPUTS}:; \
+ set -e; builddir=$$PWD; \
+ pushd $(srcdir); $(TEX) -output-directory=$$builddir </dev/null $*; popd; \
+ while grep 'Rerun to get' $*.log > /dev/null ; do \
+ pushd $(srcdir); $(TEX) -output-directory=$$builddir </dev/null $*; popd; \
+ done; \
+ if grep '^\\bibdata{' *.aux > /dev/null \
+ && grep '^\\citation{' *.aux > /dev/null; \
+ then \
+ BSTINPUTS=.:$(srcdir):${BSTINPUTS}: BIBINPUTS=.:$(srcdir):${BIBINPUTS}: $(BIBTEX) $* || exit $$?; \
+ pushd $(srcdir); $(TEX) -output-directory=$$builddir </dev/null $*; popd; \
+ while grep 'Rerun to get' $*.log > /dev/null ; do \
+ pushd $(srcdir); $(TEX) -output-directory=$$builddir </dev/null $*; popd; \
+ done ; \
+ fi
+
+.dvi.pdf:
+ export TEXINPUTS=.:$(abs_builddir):${TEXINPUTS}:; \
+ pushd $(srcdir); \
+ $(DVIPDF) $(abs_builddir)/$*.dvi $(abs_builddir)/$*.pdf; \
+ popd
+
+.dvi.ps:
+ export TEXINPUTS=.:$(abs_builddir):${TEXINPUTS}:; \
+ pushd $(srcdir); \
+ $(DVIPS) $(abs_builddir)/$*.dvi -o $(abs_builddir)/$*.ps; \
+ popd
+
+TEXCLEANFILES = *.aux *.bbl *.blg *.log *.out *.toc *.dvi
+clean-local: latex-clean
+doc-clean-local: latex-doc-clean
+latex-clean:
+ -test -z "$(TEXCLEANFILES)" || rm -f $(TEXCLEANFILES)
+ -rm -rf auto
+
+latex-doc-clean: latex-clean
+ -rm -f *.pdf *.ps
--- /dev/null
+# -*- Makefile -*-
+# $Id$
+
+# many tests need parts of libdune. Telling the tests to use
+# previously build partial libs is possible but difficult to maintain:
+# the SUBDIRS have to be very carefully defined for this to work...
+# Additionally, testing with a partial lib is unrealistic.
+#
+# As users may try to use "make check" without a full build we
+# generate a meaningful error message instead of silently failing on a
+# lib-dependency
+
+# add a new dependency to automake-internal rule
+check-am: libcheck
+
+libcheck: libcheck-FORCE
+ @if test ! -f $(top_builddir)/lib/libdune.la ; then \
+ echo ; \
+ echo ' libdune not built, checks will not work yet!' ; \
+ echo ' Run a full make to fix this' ; \
+ echo ; \
+ exit 1; \
+ fi
+
+libcheck-FORCE:
+
+.PHONY: libcheck libcheck-FORCE
--- /dev/null
+# -*- Makefile -*-
+# $Id$
+
+sourcescheck_IGNORE = aclocal.m4 dependencies.m4
+
+sourcescheck_LIST = $(SOURCES) $(DIST_SOURCES) $(HEADERS) $(DIST_HEADERS) \
+ $(sourcescheck_NOSOURCES) $(dist_noinst_DATA) $(EXTRA_DIST)
+
+sourcescheck: sourcescheck-recursive
+
+# @(for f in $(sourcescheck_LIST) fnord; do echo $$f; done) | \
+# grep '\.[hc][hc]$$' | sort | uniq > header_CHECK.install
+sourcescheck-am:
+ @echo $(sourcescheck_LIST) | tr ' ' '\n' | \
+ grep '\.[hcm][hc4]$$' | sort | uniq > header_CHECK.install
+ @(ls $(srcdir); echo $(sourcescheck_DUMMY)) | \
+ grep '\.[hcm][hc4]$$' | sort | uniq > header_CHECK.present
+ @RESULT=0; \
+ if diff header_CHECK.* | grep ^[\<\>] -q; then \
+ echo "==== WARNING ===="; \
+ echo "Directory: $(srcdir)"; \
+ echo "Files present but not installed:"; \
+ diff -u header_CHECK.install header_CHECK.present | \
+ grep -v ^+++ | grep ^+; \
+ echo "Files listed for install but not present:"; \
+ diff -u header_CHECK.install header_CHECK.present | \
+ grep -v ^--- | grep ^-; \
+ echo "==== END ===="; \
+ RESULT=1; \
+ fi; \
+ rm -f header_CHECK.install header_CHECK.present; \
+ exit $$RESULT
+
+sourcescheck-recursive:
+ @set fnord $$MAKEFLAGS; amf=$$2; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+.PHONY: sourcescheck sourcescheck-recursive sourcescheck-am
--- /dev/null
+# -*-makefile-*-
+
+ACLOCAL_AMFLAGS=@ACLOCAL_AMFLAGS@
+DUNECONTROL=@DUNE_COMMON_ROOT@/bin/dunecontrol
+
+sourcescheck_NOSOURCES = aclocal.m4 dependencies.m4
+
+all-am: dependencies.m4
+
+@DUNE_MOD_NAME@.m4: dune.module
+ cd $(srcdir) && $(DUNECONTROL) --only=@DUNE_MOD_NAME@ m4create
+
+moduledir = $(libdir)/dunecontrol/@DUNE_MOD_NAME@
+module_DATA = dune.module
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = @DUNE_MOD_NAME@.pc
+
+maintainer-clean-local: top-clean
+
+# we use LT_OUTPUT, thus we might have a config.lt file -- remove it!
+distclean-libtool:
+ -rm -f libtool config.lt
+.PHONY: distclean-libtool
+
+top-clean:
+ rm -f dependencies.m4
--- /dev/null
+# -*- makefile -*-
+# $Id$
+
+## rules to create HTML-pages from wml-files with additional magic to
+## possibly use the layout of the Dune-homepage
+
+# if DUNEWEBDIR is set to the dune-web directory the layout and
+# install-stuff from that place will be used
+
+# CURDIR should be defined in the same way as in dune-web
+
+####
+# how to run wml
+if DUNEWEB
+WMLCMD = cd $(DUNEWEBDIR) && @WML@ --nocd -DROOT=$(BASEDIR)
+else
+WMLCMD = cd $(DUNE_COMMON_ROOT)/doc && @WML@ --nocd
+endif
+
+####
+# how to build html files
+if WML
+.wml.html:
+ if test "`dirname $<`" == "."; then \
+ input="$(abs_srcdir)/$<"; else \
+ input="$<"; fi; \
+ $(WMLCMD) -I $(abs_srcdir) $$input -o $(abs_builddir)/$@
+endif
+
+####
+# howto install into the webpage
+if DUNEWEB
+web-install-default: doc
+ if test -d $(DUNEWEBDIR) && test -r $(DUNEWEBDIR)/Make.global ; then \
+ for DIR in $(SUBDIRS) ; do \
+ $(MAKE) -C $$DIR web-install || exit 1; \
+ done ; \
+ $(MAKE) -f $(DUNEWEBDIR)/Make.global \
+ EXTRAINSTALL="$(EXTRAINSTALL)" CURDIR="$(CURDIR)" install ; \
+ fi
+else
+web-install-default:
+endif
+
+####
+# how to clean up
+web-build: $(PAGES)
+web-clean:
+ -test -z $(PAGES) || rm -f $(PAGES)
+
+doc-clean-local: web-clean
+web-install-local: web-install-default
+doc-local: web-build
--- /dev/null
+Makefile
+Makefile.in
+semantic.cache
+check-log-store
+*.swp
+xfail-compile-tests.log
+xfail-compile-tests.trs
--- /dev/null
+install(PROGRAMS
+ am2cmake.py
+ dunedoxynize
+ duneproject
+ dunecontrol
+ git-whitespace-hook
+ mpi-config
+ dune-autogen
+ DESTINATION ${CMAKE_INSTALL_BINDIR})
--- /dev/null
+# $Id$
+
+# put scripts into dist-tarball
+EXTRA_DIST = am2cmake.py CMakeLists.txt duneproject dunecontrol \
+ dunedoxynize \
+ git-whitespace-hook \
+ mpi-config dune-autogen \
+ xfail-compile-tests
+
+# ... and install some
+bin_SCRIPTS = am2cmake.py dunedoxynize duneproject dunecontrol mpi-config dune-autogen \
+ git-whitespace-hook
+
+include $(top_srcdir)/am/global-rules
--- /dev/null
+#!/bin/bash
+
+#
+# patch the include statement into all Makefile.am files
+#
+
+set -e
+
+# always start in $top_srcdir
+if ! test -f configure.ac; then
+ echo "Wrong Directory"
+ echo "run from \$top_srcdir"
+ exit 1
+fi
+
+# list of files to patch
+FILES=`find . -name Makefile.am`
+# snippet to patch into Makefile.am
+SNIP='include $(top_srcdir)/am/sourcescheck'
+# create the grep regexp from the snip
+REGEXP="^$(echo $SNIP | sed -e 's/[\$\/\(\)]/./g')\$"
+# enable / disable verbose mode
+VERBOSE=0
+
+for f in $FILES; do
+ # only patch files that don't have the patch yet
+ if ! grep -q "$REGEXP" $f; then
+ echo patching $f
+ # normalize end of file
+ while test "$(tail -1 $f)" != ""; do
+ echo >> $f
+ done
+ echo $SNIP >> $f
+ else
+ if test x$VERBOSE = x1; then
+ echo $f already patched
+ fi
+ fi
+done
--- /dev/null
+#!/usr/bin/python
+import sys
+import re
+import os
+import fnmatch
+import errno
+from optparse import OptionParser
+from pyparsing import *
+
+class rem_proc:
+ def __init__(self, name):
+ self.name=name
+ self.found=False
+ def parse(self,tokens):
+ self.found=True
+ def foreach_begin(self):
+ return "\nforeach(i ${"+self.name+"})\n"
+
+ def foreach_end(self):
+ return "endforeach(i ${"+self.name+"})\n"
+
+ def process_SUBDIRS(self):
+ return ''.join([self.foreach_begin(),
+ " if(${i} STREQUAL \"test\")\n",
+ " set(opt EXCLUDE_FROM_ALL)\n",
+ " endif(${i} STREQUAL \"test\")\n",
+ " add_subdirectory(${i} ${opt})\n",
+ " unset(opt)\n"+self.foreach_end()])
+
+ def process(self):
+ s=""
+ if self.found:
+ s= getattr(self, "process_%s" % self.name)()
+ return s
+
+
+ def process_TESTS(self):
+ return ''.join(['\n',
+ self.foreach_begin(),
+ " add_test(${i} ${i})\n",
+ self.foreach_end()])
+
+ def process_XFAIL_TESTS(self):
+ return ''.join(['\n#Set properties for failing tests\n',
+ 'set_tests_properties(\n',
+ ' ${XFAIL_TESTS} PROPERTIES\n',
+ ' WILL_FAIL true)'])
+
+ def process_COMPILE_XFAIL_TESTS(self):
+ return ''.join(['# Add test for programs that should not compile',
+ '\nforeach(_TEST ${COMPILE_XFAIL_TESTS})\n'
+ ' add_test(NAME ${_TEST}',
+ ' COMMAND ${CMAKE_COMMAND} --build . --target ${_TEST} --config $<CONFIGURATION>)\n',
+ 'endforeach(_TEST)\n',
+ 'set_tests_properties(${COMPILE_XFAIL_TESTS}\n',
+ ' PROPERTIES WILL_FAIL true)'])
+
+
+def parse_dependency(tokens):
+ tokens[0][0]='add_dependencies('+tokens[0][0]+' '
+ tokens[0][-1]=tokens[0][-1]+')'
+
+def comment_lines(tokens):
+ tokens[0][0]='# The following lines are comment out as the translation is not clear. TODO review\n#\n# '+tokens[0][0]
+ if len(tokens[0])>0:
+ for i in range(1, len(tokens[0])):
+ if tokens[0][i] == '\n':
+ tokens[0][i]='\n#'
+
+def repl_gnudir(m):
+ #print "gnudir %s" % m
+ return "CMAKE_INSTALL_"+m.upper()
+
+def parse_sources(tokens):
+ target=re.sub('_$', '', tokens[0][0])
+ tokens[0][0]='add_executable('+target+' '
+ tokens[0][-1]=tokens[0][-1]+')'
+
+class installer:
+ def __init__(self, name):
+ self.name = name
+ self.found_dirs = set()
+ self.regex= re.compile(r'(?P<prefix>\S+[^_])_'+self.name)
+ self.install_prefix = {
+ 'SCRIPTS': 'PROGRAMS',
+ 'DATA': 'FILES',
+ 'PROGRAMS': 'TARGETS',
+ 'LIBRARIES': 'TARGETS',
+ 'HEADERS': 'FILES',
+ 'check_PROGRAMS': ''
+ }[name]
+ def create_parser(self,lowercase_name,opt_ws,equals,value):
+ parser=Group(Combine(Optional(lowercase_name)+self.name)+Suppress(opt_ws)+ equals + opt_ws + Optional(value))
+ return parser
+ def parse(self,tokens):
+ #import pdb; pdb.set_trace()
+ m=self.regex.match(tokens[0][0])
+ if m:
+ self.found_dirs.add(m.group('prefix'))
+ else:
+ self.found_dirs.add('')
+
+ def process(self):
+ #import pdb; pdb.set_trace()
+ s=""
+ for i in self.found_dirs:
+ if i:
+ install_dir=i+'dir'
+ else:
+ install_dir=repl_gnudir({
+ 'SCRIPTS': 'bindir',
+ 'DATA': 'datadir',
+ 'PROGRAMS': 'bindir',
+ 'LIBRARIES': 'libdir',
+ 'HEADERS': 'includedir'
+ }[self.name])
+ if not (i == ""):
+ var=""+i+'_'+self.name
+ else:
+ var=self.name
+ if not (var.strip().startswith('noinst_')
+ or var.strip().startswith('check_')
+ or var.strip().startswith('dist_noinst_')):
+ s= s+"\ninstall("+self.install_prefix+" ${"+var+"} DESTINATION ${"+install_dir+"})"
+ return s
+
+class target_flags:
+ def __init__(self, suffix):
+ self.suffix=suffix
+ self.known_flags = {
+ 'ALBERTA_': ['add_dune_alberta_flags',''],
+ 'AM_': ['target_link_libraries', '${DUNE_LIBS}'],
+ 'ALUGRID_': ['add_dune_alugrid_flags',''],
+ 'UG_': ['add_dune_ug_flags', ''],
+ 'SUPERLU_': ['add_dune_superlu_flags', ''],
+ 'DUNEMPI': ['add_dune_mpi_flags', ''],
+ 'AMIRAMESH_': ['add_dune_amiramesh_flags',''],
+ 'BOOST_': ['add_dune_boost_flags',''],
+ 'GMP_': ['add_dune_gmp_flags',''],
+ 'GRAPE_': ['add_dune_grape_flags',''],
+ 'PARMETIS_': ['add_dune_parmetis_flags',''],
+ 'PETSC_': ['add_dune_petsc_flags',''],
+ 'PSURFACE_': ['add_dune_psurface_flags','']
+ }
+ for i in range(1,9):
+ self.known_flags.update({
+ 'ALBERTA'+str(i)+'D_' : ['add_dune_alberta_flags', ''+'GRIDDIM '+str(i)]})
+ def parse(self, stri,loc,tokens):
+ #print 'target_flags'
+ #print self.suffix
+ #print tokens
+ if (self.suffix == 'CPPFLAGS' or self.suffix=='CXXFLAGS'):
+ line=''.join(tokens[0])
+ s=''
+ for key, value in self.known_flags.items():
+ if line.find(key)>-1:
+ s+='\n'+value[0]+'('+re.sub(r'set\((.*)_', '\\1',tokens[0][0])+value[1]+')'
+ tokens[0]=s
+ #print tokens
+ else:
+ comment_lines(tokens)
+
+class dir_parser:
+ def __init__(self):
+ self.has_doxygen=False
+ def parse_dir(self,stri,loc,tokens):
+ #import pdb; pdb.set_trace()
+ #print "parse_dir"
+ #print tokens
+ tokens[0][1]=''.join(tokens[0][1:])
+ if tokens[0][1].find('doxygen')>-1:
+ self.has_doxygen=True
+ #print range(2, len(tokens[0]))
+ if len(tokens[0]) >=2:
+ for i in range(2, len(tokens[0])):
+ tokens[0].pop()
+ #print tokens
+ #print "str="+stri+" |"
+ #print "loc="+str(loc)+" |"
+ #print tokens[0][1]
+ #for i in range(0,len(tokens[0])):
+
+ tokens[0][1]=re.sub(r'\$\{([a-z]+dir)\}(\S*)\)', (lambda m: "${"+repl_gnudir(m.group(1))+"}"+m.group(2)+')'), tokens[0][1])
+ #print tokens[0][1]
+ tokens[0][1]=tokens[0][1].replace('${CMAKE_INSTALL_DATADIR}/doc',
+ '${CMAKE_INSTALL_DOCDIR}')
+ tokens[0][1]=tokens[0][1].replace('${CMAKE_INSTALL_DATAROOTDIR}/doc',
+ '${CMAKE_INSTALL_DOCDIR}')
+ #print tokens
+
+ def process(self):
+ if self.has_doxygen:
+ return '\n\n# Create and install doxygen documentation\nadd_doxygen_target()\n'
+ else:
+ return ''
+
+def parse_include(tokens):
+ tokens[0][0]='# include not needed for CMake\n# '+tokens[0][0]
+
+def parse_if(tokens):
+
+ expression = tokens[0][1]+' '
+ tokens[0][0] ='if('
+ tokens[0][2] =')\n'
+ tokens[0][len([0])-2] ='endif('+expression+')'
+ if tokens[0].elsestart :
+ tokens[0][4] ='else('+expression+')'
+
+def parse_assign(tokens):
+ tokens[0][0]='set('+tokens[0][0]+' '
+ tokens[0][-1]=tokens[0][-1]+')'
+
+def parse_append(tokens):
+ tokens[0][0]='list(APPEND '+tokens[0][0]+' '
+ tokens[0][-1]=tokens[0][-1]+')'
+
+
+def parse_var(stri,loc,tokens):
+ #print "parse_var"
+ #print tokens
+ #print "str="+stri+" |"
+ #print "loc=%s|" % loc
+ tokens[0]='${'+tokens[0]+'}'
+ #print tokens
+
+def rename_var(tokens):
+ #print 'rename_var |%s|' % tokens[0]
+ #print tokens
+ name = re.sub('[ ]*([a-zA-Z0-9_])[ ]*[\n]?', '\\1', tokens[0])
+ #print '|%s|' %name
+ tokens[0]={
+ 'ALBERTA': 'ALBERTA_FOUND',
+ 'ALUGRID': 'ALUGRID_FOUND',
+ 'AMIRAMESH': 'AMIRAMESH_FOUND',
+ 'CONVERT': 'CONVERT_FOUND',
+ 'DUNEWEB': 'DUNEWEB_FOUND',
+ 'EIGEN': 'EIGEN_FOUND',
+ 'GLUT': 'GLUT_FOUND',
+ 'GMP': 'GMP_FOUND',
+ 'GRAPE': 'GRAPE_FOUND',
+ 'INKSCAPE': 'INKSCAPE_FOUND',
+ 'MPI': 'MPI_CXX_FOUND',
+ 'PARDISO': 'PARDISO_FOUND',
+ 'PETSC': 'PETSC_FOUND',
+ 'PSURFACE': 'PSURFACE_FOUND',
+ 'SUPERLU': 'SUPERLU_FOUND',
+ 'TEX4HT': 'TEX4HT_FOUND',
+ 'UG': 'UG_FOUND',
+ 'WML': 'WML_FOUND'}.setdefault(name, tokens[0])
+ if name.startswith('HAVE_DUNE'):
+ tokens[0]=re.sub(r'have-(.*)$', '\\1', name.lower().replace('_','-'))+'_FOUND'
+ #print tokens[0]
+
+#print rename_var(['bla'])
+#print rename_var(['UG'])
+#print rename_var(['A'])
+change_var2=1
+
+def parse_var2(stri,loc,tokens):
+ if change_var2:
+ tokens[0]='${'+tokens[0]+'}'
+ else:
+ tokens[0][0]='@'+tokens[0][0]+'@'
+
+class is_present:
+ def __init__(self):
+ self.found=False
+ def parse(self,tokens):
+ self.found=True
+
+def repl_tabs(tokens):
+ for i in range(0, len(tokens)):
+ tokens[i]=tokens[i].replace('\t', ' ')
+
+def am_2_cmake_string(amstring):
+ ParserElement.setDefaultWhitespaceChars("")
+ word = Word(alphanums+"*:.-_=<>&!;,/")
+ ws=Word(' ')
+ opt_ws=Optional(ws)
+ varopen = Literal("$(")#.replaceWith("${")
+ varclose = Literal(")")#.replaceWith("}")
+ var = Combine(varopen.suppress() + Word(alphanums+"_-")+varclose.suppress())
+ var.addParseAction(rename_var)
+ var.addParseAction(parse_var)
+ var2 = Combine(Literal("@").suppress() +Word(alphanums+"_-")+Literal("@").suppress())
+ var2.setParseAction(parse_var2)
+ wordorvar = var|var2| word
+ qwordorvar=("\""+wordorvar+"\"")|wordorvar
+ NL = opt_ws.suppress() + Or(lineEnd,stringEnd)
+ #NL.setDebug()
+ multiple_words = wordorvar + ZeroOrMore( opt_ws + wordorvar)
+ qmultiple_words = ("\""+multiple_words+"\"")|multiple_words
+ word_line = qmultiple_words+ZeroOrMore(opt_ws+qmultiple_words)
+ comment = Group('#'+ restOfLine('commenttext'))
+ continuation = Suppress('\\')+LineEnd()
+ #continuation.setDebug()
+ equals = Literal("=").suppress()
+ value = ZeroOrMore(opt_ws + Optional(word_line) + opt_ws + continuation)+ opt_ws+ word_line
+ name = Word(alphanums+"_-")
+ beginif = Literal("if")
+ #beginif.setDebug()
+ lines = Forward()
+ ifexpression = restOfLine + NL
+ ifexpression.setParseAction(rename_var)
+ ifbody = Group(lines)
+ endif = Literal('endif')+restOfLine.suppress()
+ elsestatement = Forward()
+ elsestatement << (opt_ws+ Literal('else').setResultsName('elsestart') + NL + Group (lines))
+ #endif.setDebug()
+ ifstatement =Forward()
+ ifstatement << Group(beginif + ifexpression + Group(lines) + Optional(elsestatement) + opt_ws + endif)#+ NL# +endif #+ NL
+ #ifstatement.setDebug()
+ ifstatement.setParseAction(parse_if)
+
+ varAssign = Group(name + Suppress(opt_ws)+ equals + opt_ws + Optional(value))
+ varAssign.setParseAction(parse_assign)
+
+ docsAssign = Group(Or(Literal("DOCFILES"), Literal("DOCFILES_EXTRA"))+ Suppress(opt_ws)+ equals + opt_ws + Optional(value))
+ docsAssign.setParseAction(parse_assign)
+ docs_present = is_present()
+ docsAssign.addParseAction(docs_present.parse)
+ varAddAssign = Group(name + Suppress(opt_ws) + Literal('+=').suppress() + Suppress(opt_ws) + Optional(value))
+ varAddAssign.setParseAction(parse_append)
+
+ # Grammar for <lowercase>dir. A parser is needed to convert the GNU autoconf dirs to
+ # CMAKE GNU dirs.
+ dir_name = Regex("[a-z0-9_-]+dir")#Word(srange("[a-z0-9_-]"))
+ dirAssign=Group(dir_name+Suppress(opt_ws)+ equals + opt_ws + Optional(value))
+ dirAssign.setParseAction(parse_assign)
+ dirParser = dir_parser()
+ dirAssign.addParseAction(dirParser.parse_dir)
+ #dirAssign.setDebug()
+
+ lowercase_name_= Regex("[a-z0-9_-]+_")
+
+ cppflagsAssign = Group(lowercase_name_+'CPPFLAGS' + Suppress(opt_ws)+ equals + opt_ws + Optional(value))
+ cppflagsAssign.addParseAction(parse_assign)
+ cppflags=target_flags('CPPFLAGS')
+ cppflagsAssign.addParseAction(cppflags.parse)
+
+ cxxflagsAssign = Group(lowercase_name_+'CXXFLAGS' + Suppress(opt_ws)+ equals + opt_ws + Optional(value))
+ cxxflags=target_flags('CXXFLAGS')
+ cxxflagsAssign.addParseAction(parse_assign)
+ cxxflagsAssign.addParseAction(cxxflags.parse)
+
+ ldflagsAssign = Group(lowercase_name_+'LDFLAGS' + Suppress(opt_ws)+ equals + opt_ws + Optional(value))
+ ldflagsAssign.addParseAction(parse_assign)
+ ldflags=target_flags('LDFLAGS')
+ ldflagsAssign.addParseAction(ldflags.parse)
+
+ ldaddAssign = Group(lowercase_name_+'LDADD' + Suppress(opt_ws)+ equals + opt_ws + Optional(value))
+ ldaddAssign.addParseAction(parse_assign)
+ ldadd=target_flags('LDADD')
+ ldaddAssign.addParseAction(ldadd.parse)
+
+ libsAssign = Group(lowercase_name_+'LIBS' + Suppress(opt_ws)+ equals + opt_ws + Optional(value))
+ libsAssign.addParseAction(parse_assign)
+ libs=target_flags('LIBS')
+ libsAssign.addParseAction(libs.parse)
+
+
+
+
+ # Process dir_SOURCES assignment
+ sourcesAssign = Group(lowercase_name_+Suppress(Literal("SOURCES"))+Suppress(opt_ws)+ equals + Suppress(opt_ws) + Optional(value))
+ sourcesAssign.setParseAction(parse_sources)
+
+ # Process <dir>_DATA assignment
+ data_install = installer("DATA")
+ dataAssign = data_install.create_parser(lowercase_name_, opt_ws, equals, value)
+ #dataAssign.setDebug()
+ dataAssign.addParseAction(data_install.parse)
+ dataAssign.addParseAction(parse_assign)
+ #dataAssign.addParseAction(lambda tokens: data_install.parse(tokens))
+
+ # Process check_Programs but never install them
+ check_programs = installer("check_PROGRAMS")
+ check_programsAssign = check_programs.create_parser(lowercase_name_, opt_ws, equals, value)
+
+ # Process <dir>_PROGRAMS assignment
+ programs_install = installer("PROGRAMS")
+ programsAssign = programs_install.create_parser(lowercase_name_, opt_ws, equals, value)
+ programsAssign.addParseAction(programs_install.parse)
+ programsAssign.addParseAction(parse_assign)
+
+ # Process <dir>_LIBRARIES assignment
+ libraries_install = installer("LIBRARIES")
+ librariesAssign = libraries_install.create_parser(lowercase_name_, opt_ws, equals, value)
+ librariesAssign.addParseAction(libraries_install.parse)
+ librariesAssign.addParseAction(parse_assign)
+
+ # Process <dir>_SCRIPTS assignment
+ scripts_install = installer("SCRIPTS")
+ scriptsAssign = scripts_install.create_parser(lowercase_name_, opt_ws, equals, value)
+ scriptsAssign.addParseAction(scripts_install.parse)
+ scriptsAssign.addParseAction(parse_assign)
+
+ # Process <dir>_HEADERS assignment
+ headers_install = installer("HEADERS")
+ headersAssign = headers_install.create_parser(lowercase_name_, opt_ws, equals, value)
+ headersAssign.addParseAction(headers_install.parse)
+ headersAssign.addParseAction(parse_assign)
+
+ # SUBDIRS
+ subdirsAssign = Group(Combine(Literal("SUBDIRS"))+Suppress(opt_ws)+ equals + opt_ws + Optional(value))
+ subdirsAssign.setParseAction(parse_assign)
+ subdirs= rem_proc("SUBDIRS")
+ subdirsAssign.addParseAction(subdirs.parse)
+
+ testsAssign = Group(Combine(Literal("TESTS"))+Suppress(opt_ws)+ equals + opt_ws + Optional(value))
+ #testsAssign.setDebug()
+ testsAssign.setParseAction(parse_assign)
+ tests=rem_proc("TESTS")
+ testsAssign.addParseAction(tests.parse)
+
+ fail_testsAssign = Group(Combine(Literal("XFAIL_TESTS"))+Suppress(opt_ws)+ equals + opt_ws + Optional(value))
+ fail_testsAssign.setParseAction(parse_assign)
+ fail_tests=rem_proc("XFAIL_TESTS")
+ fail_testsAssign.addParseAction(fail_tests.parse)
+
+ compile_fail_testsAssign = Group(Combine(Literal("COMPILE_XFAIL_TESTS"))+Suppress(opt_ws)+ equals + opt_ws + Optional(value))
+ compile_fail_testsAssign.setParseAction(parse_assign)
+ compile_fail_tests=rem_proc("COMPILE_XFAIL_TESTS")
+ compile_fail_testsAssign.addParseAction(compile_fail_tests.parse)
+
+ # Process include lines and just comment them out.
+ includeLine = opt_ws.suppress() + Group(Literal('include') + restOfLine )
+ includeLine.setParseAction(parse_include)
+ #includeLine.setDebug()
+ rule_line = multiple_words+Combine(Optional(Literal("\\")),lineEnd)
+ dependency_rule= Group(opt_ws+word+opt_ws+Suppress(Literal(':'))+ opt_ws+multiple_words)
+ dependency_rule.setParseAction(parse_dependency)
+
+ easy_rule = Group(opt_ws+word+opt_ws+Literal(':')+ opt_ws+Optional(word_line)+opt_ws+
+ ZeroOrMore(Or(NL,continuation)+ws+Optional(word_line)+opt_ws)+NL)
+ easy_rule.setParseAction(comment_lines)
+ #easy_rule.setDebug()
+
+ lines << ZeroOrMore(opt_ws+(dependency_rule+NL|easy_rule|(sourcesAssign|dataAssign|check_programsAssign|programsAssign|librariesAssign|scriptsAssign|headersAssign|subdirsAssign|compile_fail_testsAssign|fail_testsAssign|testsAssign|dirAssign|cppflagsAssign|cxxflagsAssign|ldaddAssign|ldflagsAssign|libsAssign|varAddAssign|docsAssign|varAssign|comment|ifstatement|includeLine|Empty())+NL))
+
+ s= ''.join(lines.parseString(amstring)._asStringList())
+ #print s
+ s=s+data_install.process()
+ s=s+programs_install.process()
+ s=s+libraries_install.process()
+ s=s+scripts_install.process()
+ s=s+headers_install.process()
+ s=s+subdirs.process()
+
+ s+=tests.process()
+ s+=fail_tests.process()
+ s+=compile_fail_tests.process()
+ s+=dirParser.process()
+ if tests.found or compile_fail_tests.found:
+ s+=''.join(['\n\n# We do not want want to build the tests during make all\n',
+ '# but just build them on demand\n',
+ 'add_directory_test_target(_test_target)\n',
+ 'add_dependencies(${_test_target} ${TESTS} ${COMPILE_XFAIL_TESTS})'])
+ if docs_present.found:
+ s=s+''.join(['\n# Install documentation',
+ '\n# We assume that ${DOCFILES} and ${DOCFILES_EXTRA} are targets\n',
+ 'install(TARGETS ${DOCFILES} ${DOCFILES_EXTRA} DESTINATION ${docdir})\n'])
+
+ return s
+
+str1="""# $Id: Makefile.am 8330 2012-08-09 08:12:25Z sander $
+
+#
+## Find out which tests can be built
+#
+
+if ALBERTA
+ APROG = test-alberta-1-1 test-alberta-1-2 test-alberta-2-2 \
+ test-alberta-1-3 test-alberta-2-3 test-alberta-3-3 \
+ test-alberta-generic
+ ALBERTA_EXTRA_PROGS = test-alberta
+endif
+
+if ALUGRID
+ ALUPROG = test-alugrid
+endif
+
+if UG
+ UPROG = test-ug test-parallel-ug
+if ALUGRID
+ DGFALU_UGGRID = test-dgfalu-uggrid-combination
+else
+ DGFALU_UGGRID =
+endif
+endif
+
+#
+## Defines for gridtype.hh
+#
+GRIDTYPE=YASPGRID
+GRIDDIM=2
+
+ALBERTA_DIM = $(WORLDDIM)
+
+#
+## Some parameters for the geogrid test
+#
+COORDFUNCTION = IdenticalCoordFunction\<double,$(GRIDDIM)\>
+# COORDFUNCTION = Helix
+# COORDFUNCTION = ThickHelix
+# COORDFUNCTION = DGFCoordFunction\<$(GRIDDIM),$(GRIDDIM)\>
+# COORDFUNCTION = DGFCoordFunction\<2,3\>
+CACHECOORDFUNCTION = 0
+
+#
+## define the lists of tests to build and run
+#
+
+# tests where program to build and program to run are equal
+NORMALTESTS = test-sgrid test-oned test-yaspgrid test-geogrid $(APROG) $(UPROG) $(ALUPROG) $(DGFALU_UGGRID)
+
+# list of tests to run
+TESTS = $(NORMALTESTS)
+
+# programs just to build when "make check" is used
+check_PROGRAMS = $(NORMALTESTS)
+
+EXTRA_PROGRAMS = $(ALBERTA_EXTRA_PROGS)
+
+#
+## common flags
+#
+
+# paranoia
+DUNE_EXTRA_CHECKS = -DDUNE_DEVEL_MODE
+# output coverage
+#COVERAGE = -fprofile-arcs -ftest-coverage
+AM_CXXFLAGS = $(COVERAGE)
+AM_CPPFLAGS = @AM_CPPFLAGS@ $(DUNE_EXTRA_CHECKS)
+
+# The directory where the example grid files used for testing are located
+AM_CPPFLAGS+=-DDUNE_GRID_EXAMPLE_GRIDS_PATH=\"$(top_srcdir)/doc/grids/\"
+
+#
+## define the programs
+#
+
+test_sgrid_SOURCES = test-sgrid.cc
+
+test_oned_SOURCES = test-oned.cc
+
+test_yaspgrid_SOURCES = test-yaspgrid.cc
+test_yaspgrid_CPPFLAGS = $(AM_CPPFLAGS) \
+ $(DUNEMPICPPFLAGS)
+test_yaspgrid_LDFLAGS = $(AM_LDFLAGS) \
+ $(DUNEMPILDFLAGS)
+test_yaspgrid_LDADD = \
+ $(DUNEMPILIBS) \
+ $(LDADD)
+
+# this implicitly checks the autoconf-test as well...
+test_alberta_SOURCES = test-alberta.cc
+test_alberta_CPPFLAGS = $(AM_CPPFLAGS) $(ALBERTA_CPPFLAGS) -DGRIDDIM=$(GRIDDIM) $(GRAPE_CPPFLAGS)
+test_alberta_LDFLAGS = $(AM_LDFLAGS) $(ALBERTA_LDFLAGS) $(GRAPE_LDFLAGS)
+test_alberta_LDADD = \
+ $(GRAPE_LIBS) \
+ $(ALBERTA_LIBS) \
+ $(LDADD)
+
+test_alberta_1_1_SOURCES = test-alberta.cc
+test_alberta_1_1_CPPFLAGS = -DGRIDDIM=1 -DWORLDDIM=1 $(ALBERTA1D_CPPFLAGS) $(GRAPE_CPPFLAGS) $(AM_CPPFLAGS)
+test_alberta_1_1_LDFLAGS = $(ALBERTA1D_LDFLAGS) $(GRAPE_LDFLAGS) $(AM_LDFLAGS)
+test_alberta_1_1_LDADD = $(ALBERTA1D_LIBS) $(GRAPE_LIBS) $(LDADD)
+
+test_alberta_1_2_SOURCES = test-alberta.cc
+test_alberta_1_2_CPPFLAGS = -DGRIDDIM=1 -DWORLDDIM=2 $(ALBERTA2D_CPPFLAGS) $(GRAPE_CPPFLAGS) $(AM_CPPFLAGS)
+test_alberta_1_2_LDFLAGS = $(ALBERTA2D_LDFLAGS) $(GRAPE_LDFLAGS) $(AM_LDFLAGS)
+test_alberta_1_2_LDADD = $(ALBERTA2D_LIBS) $(GRAPE_LIBS) $(LDADD)
+
+test_alberta_2_2_SOURCES = test-alberta.cc
+test_alberta_2_2_CPPFLAGS = -DGRIDDIM=2 -DWORLDDIM=2 $(ALBERTA2D_CPPFLAGS) $(GRAPE_CPPFLAGS) $(AM_CPPFLAGS)
+test_alberta_2_2_LDFLAGS = $(ALBERTA2D_LDFLAGS) $(GRAPE_LDFLAGS) $(AM_LDFLAGS)
+test_alberta_2_2_LDADD = $(ALBERTA2D_LIBS) $(GRAPE_LIBS) $(LDADD)
+
+test_alberta_1_3_SOURCES = test-alberta.cc
+test_alberta_1_3_CPPFLAGS = -DGRIDDIM=1 -DWORLDDIM=3 $(ALBERTA3D_CPPFLAGS) $(GRAPE_CPPFLAGS) $(AM_CPPFLAGS)
+test_alberta_1_3_LDFLAGS = $(ALBERTA3D_LDFLAGS) $(GRAPE_LDFLAGS) $(AM_LDFLAGS)
+test_alberta_1_3_LDADD = $(ALBERTA3D_LIBS) $(GRAPE_LIBS) $(LDADD)
+
+test_alberta_2_3_SOURCES = test-alberta.cc
+test_alberta_2_3_CPPFLAGS = -DGRIDDIM=2 -DWORLDDIM=3 $(ALBERTA3D_CPPFLAGS) $(GRAPE_CPPFLAGS) $(AM_CPPFLAGS)
+test_alberta_2_3_LDFLAGS = $(ALBERTA3D_LDFLAGS) $(GRAPE_LDFLAGS) $(AM_LDFLAGS)
+test_alberta_2_3_LDADD = $(ALBERTA3D_LIBS) $(GRAPE_LIBS) $(LDADD)
+
+test_alberta_3_3_SOURCES = test-alberta.cc
+test_alberta_3_3_CPPFLAGS = -DGRIDDIM=3 -DWORLDDIM=3 $(ALBERTA3D_CPPFLAGS) $(GRAPE_CPPFLAGS) $(AM_CPPFLAGS)
+test_alberta_3_3_LDFLAGS = $(ALBERTA3D_LDFLAGS) $(GRAPE_LDFLAGS) $(AM_LDFLAGS)
+test_alberta_3_3_LDADD = $(ALBERTA3D_LIBS) $(GRAPE_LIBS) $(LDADD)
+
+test_alberta_generic_SOURCES = $(test_alberta_SOURCES)
+test_alberta_generic_CPPFLAGS = $(test_alberta_CPPFLAGS) -DDUNE_ALBERTA_USE_GENERICGEOMETRY=1
+test_alberta_generic_LDFLAGS = $(test_alberta_LDFLAGS)
+test_alberta_generic_LDADD = $(test_alberta_LDADD)
+
+# files for alugrid
+test_alugrid_SOURCES = test-alugrid.cc
+test_alugrid_CPPFLAGS = $(AM_CPPFLAGS) \
+ $(ALL_PKG_CPPFLAGS)
+test_alugrid_LDFLAGS = $(AM_LDFLAGS) \
+ $(ALL_PKG_LDFLAGS) \
+ -static
+test_alugrid_LDADD = \
+ $(ALL_PKG_LIBS) \
+ $(LDADD)
+
+test_geogrid_SOURCES = test-geogrid.cc functions.hh
+test_geogrid_CPPFLAGS = $(AM_CPPFLAGS) \
+ $(ALL_PKG_CPPFLAGS) \
+ -DCOORDFUNCTION=$(COORDFUNCTION) \
+ -DCACHECOORDFUNCTION=$(CACHECOORDFUNCTION)
+test_geogrid_LDFLAGS = $(AM_LDFLAGS) \
+ $(ALL_PKG_LDFLAGS)
+test_geogrid_LDADD = \
+ $(ALL_PKG_LIBS) \
+ $(LDADD)
+
+# libdune contains both libugX2 and libugX3, always test both dimensions
+test_ug_SOURCES = test-ug.cc
+test_ug_CPPFLAGS = $(AM_CPPFLAGS) \
+ $(DUNEMPICPPFLAGS) \
+ $(UG_CPPFLAGS)
+test_ug_LDFLAGS = $(AM_LDFLAGS) \
+ $(DUNEMPILDFLAGS) \
+ $(UG_LDFLAGS)
+test_ug_LDADD = \
+ $(UG_LIBS) \
+ $(DUNEMPILIBS) \
+ $(LDADD)
+
+# libdune contains both libugX2 and libugX3, always test both dimensions
+test_parallel_ug_SOURCES = test-parallel-ug.cc
+test_parallel_ug_CPPFLAGS = $(AM_CPPFLAGS) \
+ $(DUNEMPICPPFLAGS) \
+ $(UG_CPPFLAGS)
+test_parallel_ug_LDFLAGS = $(AM_LDFLAGS) \
+ $(DUNEMPILDFLAGS) \
+ $(UG_LDFLAGS)
+test_parallel_ug_LDADD = \
+ $(UG_LIBS) \
+ $(DUNEMPILIBS) \
+ $(LDADD)
+
+# Test whether you can combine the different implementations in one file
+test_dgfalu_uggrid_combination_SOURCES = test-dgfalu-uggrid-combination.cc
+test_dgfalu_uggrid_combination_CPPFLAGS = $(AM_CPPFLAGS) $(UG_CPPFLAGS) $(ALUGRID_CPPFLAGS)
+test_dgfalu_uggrid_combination_LDFLAGS = $(AM_LDFLAGS) $(UG_LDFLAGS) $(ALUGRID_LDFLAGS)
+test_dgfalu_uggrid_combination_LDADD = \
+ $(ALUGRID_LIBS) \
+ $(UG_LIBS) \
+ $(LDADD)
+
+## distribution tarball
+SOURCES = gridcheck.cc staticcheck.hh checkindexset.cc checkgeometryinfather.cc checkintersectionit.cc checkcommunicate.cc checkiterators.cc checktwists.cc check-albertareader.cc basicunitcube.hh checkadaptation.cc checkgeometry.cc checkpartition.cc checkentityseed.cc
+
+# gridcheck not used explicitly, we should still ship it :)
+EXTRA_DIST = $(SOURCES)
+
+CLEANFILES = *.gcda *.gcno semantic.cache simplex-testgrid*.dgf.* cube-testgrid*.dgf.* dgfparser.log
+
+include $(top_srcdir)/am/global-rules
+
+doxygendir = $(datadir)/doc/dune-localfunctions/doxygen
+doxygen_DATA = $(WHAT)
+
+# install the html pages
+docdir=$(datadir)/doc/dune-common/buildsystem
+if BUILD_DOCS
+ DOCFILES=buildsystem.pdf
+ EXTRA_DIST=$(DOCFILES)
+ EXTRAINSTALL=$(DOCFILES)
+endif
+
+all: $(WHAT) $(DOXYGENFILES)
+clean-local:
+ if test "x$(VPATH)" != "x" && test ! -e $(srcdir)/doxygen-tag; then \
+ if test -e $(top_srcdir)/doc/doxygen/Doxydep; then \
+ rm -rf $(SVNCLEANFILES); \
+ fi; \
+ fi
+# also build these sub directories
+SUBDIRS = doxygen buildsystem
+docdir=$(datadir)/doc/dune-common
+doc_DATA=data_bla data_blu
+doc_PROGRAMS= balla
+XFAIL_TESTS=ftest1 ftest2 ftest3
+COMPILE_XFAIL_TESTS=cftest1 cftest2
+"""
+
+#print am_2_cmake_string("""# which tests to run
+#TESTS = lagrangeshapefunctiontest \
+# monomshapefunctiontest \
+# virtualshapefunctiontest \
+# testgenericfem \
+# $(ALUPROG)
+#""")
+
+str2=''.join(['TESTS = lagrangeshapefunctiontest \\\n', '\tmonomshapefunctiontest\t\t\t\\\n', '\tvirtualshapefunctiontest\t\t\\\n', '\ttestgenericfem \\\n', '\t$(ALUPROG)\n'])
+#print "s=%s" % output
+
+def init_cmake_module(module_name):
+ return''.join(['# set up project\n',
+ 'project("'+module_name+'" C CXX)\n\n#circumvent not building docs\nset(BUILD_DOCS 1)\n\n',
+ '# general stuff\n',
+ 'cmake_minimum_required(VERSION 2.8.6)\n\n',
+ '#find dune-common and set the module path\n',
+ 'find_package(dune-common)\n'
+ 'list(APPEND CMAKE_MODULE_PATH ${dune-common_MODULE_PATH}\n'
+ ' "${CMAKE_SOURCE_DIR}/cmake/modules")# make sure our own modules are found\n\n',
+ '#include the dune macros\n'
+ 'include(DuneMacros)\n\n',
+ '# start a dune project with information from dune.module\n',
+ 'dune_project()\n\n'])
+
+def finalize_cmake_module(module_name):
+ upper_name =re.sub('-(\S)', lambda m: m.group(1).capitalize(),
+ module_name.capitalize())
+ name_wo_dasch=module_name.replace('-', '')
+ lines = ['\nadd_subdirectory(cmake/modules)\n',
+ '# finalize the dune project, e.g., generate config.h etc.\n'
+ 'finalize_dune_project(GENERATE_CONFIG_H_CMAKE)\n']
+ return ''.join(lines)
+
+def create_cmake_dirs_and_file(dirname, module_name):
+ upper_name =re.sub('-(\S)', lambda m: m.group(1).capitalize(),
+ module_name.capitalize())
+ print 'module_name %s' % module_name
+ print 'upper_name %s' % upper_name
+ dirs={'modules': os.path.join(dirname, 'cmake', 'modules')}
+ cdirs=[]
+ for dir in dirs.values():
+ try:
+ print "Creating %s" % dir
+ os.makedirs(dir)
+ except OSError as exception:
+ if exception.errno != errno.EEXIST:
+ raise
+ text="message(AUTHOR_WARNING \"TODO: Implement module test.\")"
+ output=open(os.path.join(dirs['modules'], upper_name+'Macros.cmake'), 'w')
+ output.write(text)
+ output.close()
+ # CMakeLists.txt in module directory
+ # list files *.cmake
+ all_cmake_files=[]
+ for root, dirnames, filenames in os.walk(dirs['modules']):
+ all_cmake_files.extend(fnmatch.filter(filenames,'*.cmake')[:])
+ lines=['set(modules \n ', '\n '.join(all_cmake_files), '\n)\n']
+ output=open(os.path.join(dirs['modules'], 'CMakeLists.txt'), 'w')
+ lines.extend(['install(FILES "${modules}" DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/modules)\n'])
+ output.write(''.join(lines))
+ output.close()
+
+
+def am_2_cmake(amfile, cmakefile, module_root=False):
+ output = open(cmakefile, 'w')
+ if module_root:
+ dirname=os.path.dirname(amfile)
+ dune_module_path = os.path.join(dirname, 'dune.module')
+ module_file = open(dune_module_path, 'r')
+ lines = module_file.readlines()
+ print ''.join(lines)
+ m=re.search(r'.*Module:[ \t]*(\S+)[ \t]*[\n]?.*', ''.join(lines))
+ if not m:
+ raise Exception("Could not find module name in dune.module file.")
+ module_file.close()
+ module_name=m.group(1)
+ print 'Module name is %s'% module_name
+ output.write(init_cmake_module(module_name))
+ create_cmake_dirs_and_file(dirname, module_name)
+ input = open(amfile, 'r')
+ lines = input.readlines()
+ str = ''.join(lines)
+ output.write(re.sub('\s+\n', '\n', am_2_cmake_string(str)))
+ input.close()
+ if module_root:
+ output.write(finalize_cmake_module(module_name))
+ output.close()
+
+def am_2_cmake_dir(directory):
+ for root, dirnames, filenames in os.walk(directory):
+ for filename in fnmatch.filter(filenames, 'Makefile.am'):
+ print "root=%s" % root
+ print "filename=%s" % filename
+ amfile=os.path.join(root, filename)
+ cmfile=os.path.join(root, 'CMakeLists.txt')
+ is_module_root = len(fnmatch.filter(filenames, 'dune.module'))
+
+ print ''.join(['Converting ', amfile, ' -> ', cmfile])
+ print is_module_root
+ am_2_cmake(amfile, cmfile, is_module_root)
+
+ # Add doxygen target
+ doxygendir=os.path.join(directory, 'doc', 'doxygen')
+ if os.path.isdir(doxygendir) and os.path.exists(os.path.join(doxygendir, 'Doxylocal')):
+ output=open(os.path.join(doxygendir, 'CMakeLists.txt'),'a')
+ output.write('\n'.join(['# Create Doxyfile.in and Doxyfile, and doxygen documentation',
+'add_doxygen_target()']))
+ output.close()
+ # Add directives to create CMake packe configuration files with autotools
+ output=open("Makefile.am'", "a")
+ output.write('\n'.join(['', '# Generate package configuration files for finding',
+ '# installed modules with CMake',
+ 'include $(top_srcdir)/am/cmake-pkg-config\n']))
+ output.close()
+
+def main():
+ usage = "usage: am2cmake "
+ parser = OptionParser(usage=usage)
+ parser.add_option("-a", "--am-file", dest="amfile",
+ help="The Makefile.am", metavar="FILE")
+ parser.add_option("-c", "--cmake-file",
+ dest="cmakefile",
+ help="The CMake file")
+ parser.add_option("-d", "--directory",
+ dest="directory",
+ help="Root directory of dune-module")
+ (options, args) = parser.parse_args()
+ if not options.amfile and not options.directory:
+ parser.error("options -a or option -d has to be present")
+ if options.directory and (options.amfile or options.cmakefile):
+ parser.error("Cannot provide a directory and a CMake or am file.")
+ if not options.cmakefile and not options.directory:
+ options.cmakefile = options.amfile.replace('Makefile.am', 'CMakeLists.txt')
+
+ #import pdb; pdb.set_trace()
+ if options.directory:
+ am_2_cmake_dir(options.directory)
+ else:
+ print ''.join([options.amfile, '->', options.cmakefile])
+ am_2_cmake(options.amfile, options.cmakefile)
+if __name__ == "__main__":
+ main()
--- /dev/null
+#!/bin/sh
+
+set -e
+
+# DB format
+#
+# <tag> <revision> <host> <mode> <module> <path> <errors> <warnings> <log>
+
+# parameter:
+# $(LOG_FILE) $(LOG_DIR) "build" "$$target" "$$path"
+
+host="@hostid@"
+tag="@tag@"
+revision="@revision@"
+
+logfile="$1"
+logdir="$2"
+mode="$3"
+module="`basename $4`"
+path="$5"
+errors="$6"
+warnings="$7"
+
+test -d $logdir || mkdir $logdir
+
+storelog=`tempfile -d $logdir`
+
+trap "rm -f $storelog" EXIT
+
+if true; then
+ echo "TAG: $tag"
+ echo "REVISION: $revision"
+ echo "HOST: $host"
+ echo "MODE: $mode"
+ echo "MODULE: $module"
+ echo "PATH: $path"
+ if test "x$errors" != x; then
+ echo "ERRORS: $errors"
+ fi
+ if test "x$warnings" != x; then
+ echo "WARNINGS: $warnings"
+ fi
+ echo "LOG:"
+ cat $logfile
+fi > $storelog
+
+trap - EXIT
--- /dev/null
+#!/bin/bash
+# $Id: autogen.sh 5054 2008-01-08 15:06:55Z christi $
+
+# barf on errors
+set -e
+
+usage () {
+ echo "Usage: dune-autogen DUNE_MODULE_PATH_LIST [options]"
+ echo " --ac=, --acversion=VERSION use a specific VERSION of autoconf"
+ echo " --am=, --amversion=VERSION use a specific VERSION of automake"
+ echo " -h, --help you already found this :-)"
+}
+
+## get my name...
+grep '^Module:' dune.module >/dev/null || echo "Parser Error: Module entry missing in dune.module"
+name=
+while read head name rest
+do case "$head" in
+ Module:) break;;
+ Module:*) name="${head#Module:}"; break;;
+ esac
+ name=
+done <dune.module
+
+## dune-all.m4
+rm -f dune-all.m4
+rm -f $name.m4
+
+# add current dir to PATH
+PATH=`dirname "$0"`:$PATH
+
+# guess libtool prefix
+if test -n "$LIBTOOLIZE"; then
+ LIBTOOL_prefix=`dirname "\`dirname "$LIBTOOLIZE"\`"`
+ PATH=$LIBTOOL_prefix:$PATH
+ ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I \"$LIBTOOL_prefix/share/aclocal\""
+fi
+
+for OPT in "$@"; do
+ set +e
+ # stolen from configure...
+ # when no option is set, this returns an error code
+ arg=`expr "x$OPT" : 'x[^=]*=\(.*\)'`
+ set -e
+
+ case "$OPT" in
+ --ac=*|--acversion=*)
+ if test "x$arg" = "x"; then
+ usage;
+ exit 1;
+ fi
+ ACVERSION=$arg
+ ;;
+ --am=*|--amversion=*)
+ if test "x$arg" = "x"; then
+ usage;
+ exit 1;
+ fi
+ AMVERSION=$arg
+ ;;
+ -h|--help) usage ; exit 0 ;;
+ *)
+ if test -d "$OPT/m4"; then
+ ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I \"$OPT/m4\""
+ fi
+ if test -z "$am_dir"; then
+ # if am_dir is already set, then we already find dune-common
+ # and did set am_dir correctly.
+ if test -f "$OPT/dune-common.pc.in" ; then
+# if test \( -d "$OPT/am" \) -a ! \( -h "$OPT/am" \) ; then
+ echo "Found am directory $OPT/am"
+ am_dir="$OPT/am"
+ fi
+ if test -d "$OPT/share/dune/aclocal"; then
+ ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I $OPT/share/dune/aclocal"
+ fi
+ if test -d "$OPT/share/aclocal"; then
+ ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I $OPT/share/aclocal"
+ fi
+ if test -d "$OPT/share/dune-common/am"; then
+ echo "Found am directory $OPT/share/dune-common/am"
+ am_dir="$OPT/share/dune-common/am"
+ fi
+ fi
+ PATH=$OPT/bin:$PATH
+ ;;
+ esac
+done
+
+## report parameters
+if test "x$ACVERSION" != "x"; then
+ echo "Forcing autoconf version «$ACVERSION»"
+ if ! which autoconf$ACVERSION > /dev/null; then
+ echo
+ echo "Error: Could not find autoconf$ACVERSION"
+ echo " Did you specify a wrong version?"
+ exit 1
+ fi
+fi
+if test "x$AMVERSION" != "x"; then
+ echo "Forcing automake version «$AMVERSION»"
+ if ! which automake$AMVERSION > /dev/null; then
+ echo
+ echo "Error: Could not find automake$AMVERSION"
+ echo " Did you specify a wrong version?"
+ exit 1
+ fi
+fi
+
+## run autotools
+
+echo "--> dunedoxynize..."
+dunedoxynize
+
+echo "--> libtoolize..."
+# this script won't rewrite the files if they already exist. This is a
+# PITA when you want to upgrade libtool, thus I'm setting --force
+if [ x`type -t glibtoolize` = xfile ]; then
+ LIBTOOLIZE=glibtoolize
+fi
+${LIBTOOLIZE-libtoolize} --force
+
+# writing privat m4 file
+echo -n "--> "
+dunecontrol --only=$name m4create
+
+# prepare everything
+echo "--> aclocal..."
+rm -f aclocal.m4
+rm -rf autom4te.cache
+eval aclocal$AMVERSION "-I . $ACLOCAL_FLAGS"
+
+# create a link to the dune-common am directory
+if [ "$name" != "dune-common" ]; then
+ if [ -n "$am_dir" ] && [ -d "$am_dir" ]; then
+ echo "--> linking dune-common/am..."
+ rm -f am
+ ln -s "$am_dir" am
+ else
+ echo
+ echo "Error: Could not find dune-common/am!"
+ usage
+ exit 1
+ fi
+fi
+
+# applications should provide a config.h for now
+echo "--> autoheader..."
+autoheader$ACVERSION
+
+echo "--> automake..."
+automake$AMVERSION -W all --add-missing
+
+echo "--> autoconf..."
+autoconf$ACVERSION
+
+## tell the user what to do next
+echo "Now run ./configure to setup $name"
--- /dev/null
+#!/bin/bash
+
+set -e
+
+###############################################
+###
+### check for environment variables
+###
+
+if test -z "$MAKE"; then
+ MAKE=make
+fi
+
+###############################################
+###
+### read lib
+###
+
+canonicalname(){
+ if test $# -ne 1; then
+ echo Usage: canonicalname path >&2
+ return 1
+ fi
+ file="`eval echo $1`" # expand ~
+ if test ! -e "$file"; then
+ echo $file: file not found >&2
+ return 1
+ fi
+ # if this is a symlink, then follow the symlink
+ if test -L "$file"; then
+ fdir="`dirname \"$file\"`"
+ flink="`readlink \"$file\"`"
+ if test -e "$flink"; then
+ # these are absolute links, or links in the CWD
+ canonicalname "$flink"
+ else
+ canonicalname "$fdir/$flink"
+ fi
+ else
+ # if this is a file, then remember the filename and
+ # canonicalize the directory name
+ if test -f "$file"; then
+ fdir="`dirname \"$file\"`"
+ fname="`basename \"$file\"`"
+ fdir="`canonicalname \"$fdir\"`"
+ echo "$fdir/$fname"
+ fi
+ # if this is a directory, then create an absolute
+ # directory name and we are done
+ if test -d "$file"; then
+ (cd "$file"; pwd)
+ fi
+ fi
+}
+
+canonicalpath(){
+ if test $# -ne 1; then
+ echo Usage: canonicalpath path >&2
+ return 1
+ fi
+ dirname "`canonicalname "$1"`"
+}
+
+checkdebug () {
+ while test $# -gt 0; do
+ if test x$1 = x--debug; then
+ echo yes
+ return
+ fi
+ shift
+ done
+ echo no
+}
+
+DEBUG=`checkdebug $@`
+if test "x$DEBUG" = "xyes"; then
+ set -x
+ set -v
+fi
+
+
+onbuildfailure() {
+ echo "Terminating $(basename "$0") due to previous errors!" >&2
+ exit 1
+}
+
+#
+# for each module load the $CONTROL script part and run $command
+#
+# parameters:
+# $1 list of modules
+# $2-$* commands + parameters to execute
+#
+build_module() {
+ local module=$1
+ shift
+ while test $# -gt 0; do
+ # get command
+ command=$1
+ shift
+
+ # only load other parameters
+ load_opts NONE
+ # get command options
+ CMD_FLAGS=
+ while test $# -gt 0 && test "$1" != ":"; do
+ COMMAND=$(echo $command | tr '[:lower:]' '[:upper:]')
+ # setup paramter list
+ CMD_FLAGS="$CMD_FLAGS \"$1\""
+ shift
+ done
+ if test -z "$CMD_FLAGS"; then
+ load_opts $command
+ else
+ # disable usage of opts file
+ if test "x$DUNE_OPTS_FILE" != "x"; then
+ echo "WARNING: commandline parameters will overwrite setting in opts file \"$DUNE_OPTS_FILE\""
+ fi
+ fi
+
+ # skip command delimiter
+ if test "$1" = ":"; then shift; fi
+
+ # actually run the commands (we already know that these are valid commands)
+ local runcommand=run_$command
+
+ # build the modules
+ local path="$(eval "echo \$PATH_${module}")"
+ eval echo "--- calling $command for \$NAME_${module} ---"
+ trap onbuildfailure EXIT
+ if ! (
+ set -e
+ cd "$path"
+ export module
+ eval_control $runcommand "$path/$CONTROL"
+ ); then eval echo "--- Failed to build \$NAME_${module} ---"; exit 1; fi
+ trap onfailure EXIT
+
+ eval echo "--- \$NAME_${module} done ---"
+ done
+}
+
+#
+# load command options from an opts file
+# the name of the opts file is stored in the global variable $DUNE_OPTS_FILE
+#
+# parameters:
+# $1 command
+#
+load_opts() {
+ local command=$1
+ local COMMAND=$(echo $command | tr '[:lower:]' '[:upper:]')
+ CMD_FLAGS=$(eval echo \$${COMMAND}_FLAGS)
+ local CMD_FLAGS_FROM_FILE=""
+ if test "$command" = "NONE"; then
+ BUILDDIR=$DUNE_BUILDDIR
+ USE_CMAKE=$DUNE_USE_CMAKE
+ if test "x$DUNE_OPTS_FILE" != "x"; then
+ if test -z "$BUILDDIR"; then
+ # no builddir set yet, use build dir from opts file if set
+ # Note: if --use-buiddir is used BUILDDIR will be set already
+ OPTS_FILE_BUILDDIR="$(eval BUILDDIR=""; . $DUNE_OPTS_FILE; eval echo \$BUILDDIR)"
+ if test -n "$OPTS_FILE_BUILDDIR"; then
+ BUILDDIR="$OPTS_FILE_BUILDDIR"
+ fi
+ fi
+ if test -z "$USE_CMAKE"; then
+ # no USE_CMAKE set yet, use USE_CMAKE from opts file if set
+ # Note: if --use-cmake is used USE_CMAKE will be set already
+ OPTS_FILE_USE_CMAKE="$(eval USE_CMAKE=""; . $DUNE_OPTS_FILE; eval echo \$USE_CMAKE)"
+ if test -n "$OPTS_FILE_USE_CMAKE"; then
+ USE_CMAKE="$OPTS_FILE_USE_CMAKE"
+ fi
+ fi
+ if test -n "$USE_CMAKE" && test -z "$CMAKE"; then
+ # We use cmake for building, but CMAKE is not yet set.
+ # Check the opts file for it
+ OPTS_FILE_CMAKE="$(eval CMAKE=""; . $DUNE_OPTS_FILE; eval echo \$CMAKE)"
+ if test -n "$OPTS_FILE_CMAKE"; then
+ CMAKE="$OPTS_FILE_CMAKE"
+ fi
+ fi
+ fi
+ fi
+ if test -n "$USE_CMAKE" && test -z "$CMAKE"; then
+ # fall back to system cmake
+ CMAKE=cmake
+ fi
+ if test "x$DUNE_OPTS_FILE" != "x"; then
+ if test "$command" = "configure"; then
+ CMAKE_FLAGS="$(. $DUNE_OPTS_FILE; eval echo \$CMAKE_FLAGS)"
+ fi
+ CMD_FLAGS_FROM_FILE="$(eval ${COMMAND}_FLAGS=""; . $DUNE_OPTS_FILE; eval echo \$${COMMAND}_FLAGS)"
+ fi
+ if test -n "$CMD_FLAGS_FROM_FILE"; then
+ echo "----- using default flags \$${COMMAND}_FLAGS from $DUNE_OPTS_FILE -----"
+ CMD_FLAGS=$CMD_FLAGS_FROM_FILE
+ elif test -n "$CMD_FLAGS"; then
+ echo "----- using default flags \$${COMMAND}_FLAGS from environment -----"
+ fi
+
+ if test "x$USE_CMAKE" = "xyes"; then
+ if test -z "$BUILDDIR"; then
+ echo "No build directory provided. Defaulting to the sub directory build-cmake"
+ export BUILDDIR=build-cmake
+ fi
+ fi
+}
+
+space=" "
+tab=" "
+BLANK="$space$tab"
+
+if test -z "$GREP"; then
+ GREP=grep
+fi
+if test -z "$SED"; then
+ SED=sed
+fi
+# Uses the current compiler to extract information about the
+# multiarch triplets and sets the export variable MULTIARCH_LIBDIR
+# according to it.
+# If not compiler is specified then cc or gcc is used.
+extract_multiarch(){
+ set +e #error in the multiarch detection should not be fatal.
+ local my_cxx_compiler
+ if test "x$MULTIARCH_LIBDIR" != "x"; then
+ return
+ fi
+ if test "x$USE_CMAKE" = "xyes"; then
+ load_opts "cmake"
+ fi
+ if test "x$my_cxx_compiler" == "x"; then
+ load_opts "configure"
+ fi
+ my_cxx_compiler=`echo $CMD_FLAGS | $GREP CXX | $SED "s/.*CXX=[\"']\{0,1\}\([^$BLANK'\"]*\)[\"']\{0,1\}.*/\1/"`
+ if test "x$my_cxx_compiler" == "x"; then
+ $(which cc &>/dev/null)
+ if test $? -eq "0"; then
+ my_cxx_compiler=cc
+ else
+ my_cxx_compiler=gcc
+ fi
+ fi
+ multiarch=$($my_cxx_compiler --print-multiarch 2>/dev/null)
+ if test $? -gt 0; then
+ for i in "target=" "Target:"; do
+ multiarch=$($my_cxx_compiler -v 2>&1| $GREP "$i" | $SED "s/.*$i[$BLANK]*\([a-z0-9_-]*\)/\1/" | $SED "s/-[a-z]*-linux-gnu/-linux-gnu/")
+ if test -n "$multiarch"; then break; fi
+ done
+ fi
+ set -e # set to old value.
+ export MULTIARCH_LIBDIR="lib/$multiarch"
+}
+
+export PREFIX_DIR="`canonicalpath "$0"`/.."
+
+# Read the modules find part
+. "$PREFIX_DIR/lib/dunemodules.lib"
+
+###############################################
+
+
+###############################################
+###
+### Commands
+###
+
+# check all parameter
+check_commands() {
+ while test $# -gt 0; do
+ # get command
+ command=$1
+ shift
+ # skip command options
+ while test $# -gt 0 && test "$1" != ":"; do
+ shift
+ done
+ # skip command delimiter
+ if test "$1" = ":"; then shift; fi
+ # test the commands
+ if ! is_command $command; then
+ usage
+ echo "ERROR: unknown command \"$command\"" >&2
+ exit 1
+ fi
+ done
+}
+
+# check wheteher the parameter is valid command or not
+is_command() {
+eval '
+case "$1" in
+ '`echo $COMMANDS | $SED -e 's/ / | /g'`')
+ return 0
+ ;;
+ *)
+ return 1
+ ;;
+esac'
+}
+
+# list of all dunecontrol commands
+COMMANDS="printdeps vcsetup update autogen configure make all exec bexec status svn git"
+
+# help string for the commands
+printdeps_HELP="print recursive dependencies of a module"
+vcsetup_HELP="setup version control repository (Git etc.) or working copy (SVN)"
+update_HELP="updated all modules from the repository"
+autogen_HELP="run the autogen.sh script for each module. Does nothing, if CMake is activated"
+configure_HELP="run configure or cmake for each module"
+make_HELP="run make for each module"
+all_HELP="\trun 'autogen', 'configure' and 'make' command for each module"
+exec_HELP="execute an arbitrary command in each module source directory"
+bexec_HELP="execute an arbitrary command in each module build directory"
+status_HELP="show vc status for all modules"
+svn_HELP="\trun svn command for each svn managed module"
+git_HELP="\trun git command for each git managed module"
+
+#
+# setup command proxies
+# call will be forwarded to run_default_$command
+#
+
+for command in $COMMANDS; do
+ eval "run_$command () { run_default_$command; }"
+done
+
+#
+# default implementations for commands...
+# these can be overwritten in the $CONTROL files
+#
+
+run_default_exec () { bash -c "eval $CMD_FLAGS"; }
+
+run_default_bexec () {
+ if test -d "$BUILDDIR"; then
+ bash -c "cd \"$BUILDDIR\" && eval $CMD_FLAGS";
+ else
+ eval echo "Build directory \\\"$BUILDDIR\\\" not found, skipping bexec for \$NAME_${module}"
+ fi
+}
+
+run_default_status () {
+ local verbose=0
+ local update=""
+ local is_git=""
+ local is_svn=""
+ name="$(eval echo \$NAME_$module)"
+
+ if test -d .git; then is_git=1; fi
+ if test -d .svn; then is_svn=1; fi
+ if test ! "$is_svn" -a ! "$is_git" ; then
+ echo "module $name not under known version control"
+ return
+ fi
+
+ for i in $CMD_FLAGS; do
+ if eval test "x$i" = "x-v"; then verbose=1; fi
+ if eval test "x$i" = "x-vv"; then verbose=2; fi
+ if eval test "x$i" = "x-u"; then update="-u"; fi
+ done
+ # is out output connected to a tty?
+ if test -t 1; then
+ blue="\e[1m\e[34m"
+ green="\e[1m\e[32m"
+ red="\e[1m\e[31m"
+ reset="\e[0m\e[0m"
+ fi
+
+ if test $verbose -eq 1; then
+ test "$is_svn" && svn status $update | $GREP -E "^M|^A|^D|^C|^U"
+ test "$is_git" && git status -uno
+ elif test $verbose -eq 2; then
+ test "$is_svn" && svn status $update
+ test "$is_git" && git status
+ fi
+
+
+ if test "$is_svn" ; then
+ changed=$(svn status | $GREP -E "^M|^A|^D" | wc -l)
+ collisions=$(svn status | $GREP -E "^C"| wc -l)
+ pending=$(svn status $update | $GREP -E "^...... \* " | wc -l)
+ fi
+ if test "$is_git" ; then
+ changed=$(git status --porcelain | $GREP -E "^ *M|^ *A|^ *D|^ *R|^ *C" | wc -l)
+ collisions=$(git status --porcelain | $GREP -E "^ *U"| wc -l)
+ pending=$(git status | $GREP -E "^\# Your branch is ahead |^\# Your branch is behind " | wc -l)
+ fi
+ color=$green
+ text="no changes"
+ if [ $changed -eq 0 ]; then
+ true
+ elif [ $changed -eq 1 ]; then
+ color=$blue;
+ text="1 change"
+ else
+ color=$blue;
+ text="$changed changes"
+ fi
+ if [ $pending -eq 0 ]; then
+ true
+ elif [ $pending -eq 1 ]; then
+ color=$blue;
+ text="$text, 1 update pending"
+ else
+ color=$blue;
+ text="$text, $pending updates pending"
+ fi
+ if [ $collisions -eq 0 ]; then
+ true
+ elif [ $collisions -eq 1 ]; then
+ color=$red
+ text="$text, 1 collision"
+ else
+ color=$red
+ text="$text, $count collisions"
+ fi
+ echo -e "$color[$text]$reset $name"
+}
+
+run_default_vcsetup() {
+ # load user options
+ if [ -n "$CMD_FLAGS" ]; then
+ eval "$CMD_FLAGS"
+ fi
+
+ # Check for both a file and a directory to cope with Git submodules
+ if [ -d .git -o -f .git ] ; then
+
+ # Read Whitespace-Hook setting from dune.module file
+ local SETUPGITHOOK="$($GREP -i "^[$BLANK]*Whitespace-Hook:" dune.module | cut -d ':' -f2 | eval $PARSER_TRIM | tr '[:upper:]' '[:lower:]')"
+
+ if [ "x$SETUPGITHOOK" = "xyes" ]; then
+ # we have to install the Git whitespace hook
+
+ # The current Git repository might be a submodule, so we have to start by
+ # determining the location of the commit hook
+
+ if [ -f .git ] ; then
+ # submodule -> .git contains a pointer to the repository
+ GITHOOKPATH="$($SED 's/gitdir: //' < .git)/hooks/pre-commit"
+ else
+ # standard case, .git is the repository
+ GITHOOKPATH=.git/hooks/pre-commit
+ fi
+
+ if [ -n "$DISABLEWHITESPACEHOOK" ] ; then
+ # the user doesn't want the Git whitespace hook - deinstall it if necessary and warn the user
+ echo "WARNING: The current module wants to install the DUNE whitespace hook, but you have disabled the hook in your options!"
+ echo "WARNING: You will have to make sure that your commits don't introduce any trailing whitespace or indentation with tabs!"
+ echo "WARNING: Otherwise, your commits might be rejected when trying to push them to an official repository!"
+
+ if [ -e "$GITHOOKPATH" ]; then
+ # there is a pre-commit hook, check whether it is our whitespace hook
+ local HOOKTAG="$(eval head -n 2 \"$GITHOOKPATH\" | tail -n 1)"
+ if [ "x$HOOKTAG" = "x# dune-git-whitespace-hook" ]; then
+ echo "--> Removing DUNE whitespace hook as requested by the user"
+ rm "$GITHOOKPATH"
+ fi
+ fi
+ else
+ # standard handling of Git whitespace hook
+ if [ ! -e "$GITHOOKPATH" ]; then
+ # there is no hook yet, we can safely install ours
+ echo "--> Installing Git pre-commit hook to enforce whitespace policy"
+ cp -p "$PREFIX_DIR/bin/git-whitespace-hook" "$GITHOOKPATH"
+ else
+ # there is already a hook, check whether it is our whitespace hook
+ local HOOKTAG="$(eval head -n 2 \"$GITHOOKPATH\" | tail -n 1)"
+ if [ "x$HOOKTAG" = "x# dune-git-whitespace-hook" ]; then
+ if [ "$PREFIX_DIR/bin/git-whitespace-hook" -nt "$GITHOOKPATH" ]; then
+ echo "--> Updating Git pre-commit hook with newer version"
+ cp -p "$PREFIX_DIR/bin/git-whitespace-hook" "$GITHOOKPATH"
+ fi
+ else
+ echo "WARNING: Existing pre-commit hook found!"
+ echo "WARNING: Skipping installation of DUNE whitespace hook!"
+ echo "WARNING: If you want to contribute patches to DUNE, you should make sure to call the whitespace hook"
+ echo "WARNING: (dune-common/bin/git-whitespace-hook) from you custom pre-commit hook, otherwise your commits"
+ echo "WARNING: might contain trailing whitespace and will not apply cleanly to the official repositories!"
+ fi
+ fi
+ fi
+ fi
+
+ # Apply git configuration settings
+ if [ -f .vcsetup/config ]; then
+ echo -n "--> Setting Git configuration entries... "
+ cat .vcsetup/config | while read; do
+ # Filter out comments
+ local COMMENT="$(echo $REPLY | $GREP '^#')"
+ if [ ! "x$COMMENT" = "x$REPLY" ]; then
+ # parse line into an array first to catch obvious syntax errors
+ # like 'option value; rm -rf /'
+ eval local GIT_ARGS=($REPLY)
+ git config "${GIT_ARGS[@]}"
+ fi
+ done
+ echo "done"
+ fi
+
+ # Apply user supplied configuration settings
+ if [ -n "$GIT_CONFIG_FILE" ]; then
+ if [ -f "$GIT_CONFIG_FILE" ]; then
+ echo -n "--> Setting custom Git configuration entries from '$GIT_CONFIG_FILE'... "
+ cat "$GIT_CONFIG_FILE" | while read; do
+ # Filter out comments
+ local COMMENT="$(echo $REPLY | $GREP '^#')"
+ if [ ! "x$COMMENT" = "x$REPLY" ]; then
+ # parse line into an array first to catch obvious syntax errors
+ # like 'option value; rm -rf /'
+ eval local GIT_ARGS=($REPLY)
+ git config "${GIT_ARGS[@]}"
+ fi
+ done
+ echo "done"
+ else
+ echo "WARNING: custom Git config file '$GIT_CONFIG_FILE' not found!"
+ fi
+ fi
+
+ fi
+
+ # Run custom setup scripts
+ if [ -d .git -o -f .git -o -d .svn -o -d CVS -o -f stamp-vc ]; then
+ if [ -d .vcsetup/run.d ]; then
+ for SCRIPT in .vcsetup/run.d/* ; do
+ if [ -x "$SCRIPT" ]; then
+ echo "--> Running $SCRIPT"
+ "$SCRIPT"
+ fi
+ done
+ fi
+ fi
+}
+
+run_default_update () {
+ DUNELINK=0
+ if test -L dune; then
+ rm dune
+ DUNELINK=1
+ fi
+ if test -d .svn; then
+ svn update
+ elif test -d CVS; then
+ cvs update -dP
+ elif test -d .git; then
+ if test -d ".git/svn" && test -n "`git svn find-rev HEAD`"; then
+ # If the current HEAD points to a SVN commit, update via git-svn
+ git svn rebase
+ else
+ # Update all remotes (if any)
+ git remote update
+
+ # merge all changes fast-forward style if possible
+ if ! git merge --ff-only FETCH_HEAD 2> /dev/null; then
+ echo "$module seems to be using git, and could not be"
+ echo "updated automatically. Please update it manually."
+ echo "(Usually, this is done via 'git svn rebase' for modules using"
+ echo "subversion or 'git merge' for modules which use git natively."
+ echo "Conflicts can be resolved using 'git mergetool'.)"
+ fi
+ fi
+ else
+ echo "WARNING: $module is not under a known version control system."
+ echo " We support svn, git and cvs."
+ fi
+ if test "$DUNELINK" != 0 && ! test -d dune; then
+ echo "WARNING: $module is using the deprecated dune symlink"
+ ln -s . dune
+ fi
+}
+
+run_default_autogen () {
+ if test "x$USE_CMAKE" != "xyes" || test ! -e "$(eval "echo \$PATH_$module")/CMakeLists.txt" ; then
+ PARAMS="$CMD_FLAGS"
+ local M4_PATH=""
+ if test -f configure.ac && \
+ ( test -d .svn || test -d .git || test -d CVS || test -f stamp-vc ); then
+ sort_modules $MODULES
+ for m in $MODULES; do
+ path="$(eval "echo \$PATH_$m")"
+ MODULE_PATHS="$MODULE_PATHS\"$path\" "
+ done
+ if test -f autogen.sh; then
+ eval echo "WARNING: \$NAME_$module contains obsolete autogen.sh," \
+ >&2
+ echo " dune-autogen is used instead." >&2
+ fi
+ eval "\"$PREFIX_DIR/bin/dune-autogen\"" "$MODULE_PATHS" "$PARAMS" || exit 1
+ else
+ echo Skipping dune-autogen
+ fi
+ else
+ echo Skipping dune-autogen because of CMake
+ fi
+}
+
+run_default_configure () {
+ extract_multiarch
+ PARAMS="$CMD_FLAGS"
+ if test "x$USE_CMAKE" = "xyes" && test -e "$(eval "echo \$PATH_$module")/CMakeLists.txt"; then
+ LOCAL_USE_CMAKE=yes
+ else
+ LOCAL_USE_CMAKE=no
+ fi
+
+ if test -x configure || test "x$LOCAL_USE_CMAKE" = "xyes" ; then
+ ACLOCAL_FLAGS="-I ."
+ if test -d "m4"; then
+ ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I m4"
+ fi
+ MY_MODULES=
+ # get dependencies & suggestions
+ sort_modules $module
+ for m in $MODULES; do
+ path="$(eval "echo \$PATH_$m")"
+ if test "x$LOCAL_USE_CMAKE" = "xyes"; then
+ #
+ # Translate the configure PARMS to cmake
+ export PARAMS
+ export CMAKE_PARAMS
+ module_translate_options_am2cmake $m $path/lib
+ fi
+ if test x$module = x$m; then continue; fi # skip myself
+ name=$(eval "echo \$NAME_$m")
+ for dir in $path/m4 $path/share/dune/aclocal $path/share/aclocal; do
+ if test -d "$dir"; then
+ ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I $dir"
+ fi
+ done
+ if test -d "$path/$BUILDDIR"; then
+ PARAMS="$PARAMS \"--with-$name=$path/$BUILDDIR\""
+ else
+ if test x$(eval echo \$INST_$m) != xyes; then
+ PARAMS="$PARAMS \"--with-$name=$path\""
+ fi
+ fi
+ if test "x$LOCAL_USE_CMAKE" = "xyes"; then
+ if test -d "$path/$BUILDDIR"; then
+ CMAKE_PARAMS="$CMAKE_PARAMS \"-D""$name""_DIR=$path/$BUILDDIR\""
+ else
+ TMP_PARAMS="\"-D""$name""_DIR=$path\""
+ for i in $MULTIARCH_LIBDIR lib lib64 lib32; do
+ if test -d "$path/$i/cmake/$name"; then
+ TMP_PARAMS="\"-D""$name""_DIR=$path/$i/cmake/$name\""
+ break;
+ fi
+ done
+ CMAKE_PARAMS="$CMAKE_PARAMS $TMP_PARAMS"
+ fi
+ fi
+ done
+
+ if test "x$HAVE_duneweb" == "xyes"; then
+ PARAMS="$PARAMS \"--with-duneweb=$PATH_duneweb\""
+ fi
+
+ if test "x$LOCAL_USE_CMAKE" = "xyes"; then
+ # we have to export the compiler and compiler flags
+ # such that they are honored by cmake.
+ flags="CXX CC CXXFLAGS CFLAGS CPPFLAGS LDFLAGS F77 FFLAGS FLIBS FC FCFLAGS FCLIBS LIBS"
+ for i in $flags; do
+ cflags=`echo "$PARAMS" | $GREP $i= | $SED -e "s/.*\($i=\"[^\"]*\"\).*/\1/" -e "s/.*\($i='[^']*'\).*/\1/"`
+ if test -n "$cflags" && test "$PARAMS" != "$cflags" ; then
+ PREPARAMS="$PREPARAMS $cflags"
+ else
+ cflags=`echo "$PARAMS" | $GREP $i= | $SED -e "s/.*\($i=[^$BLANK]*\).*/\1/"`
+ if test -n "$cflags" && test "$PARAMS" != "$cflags" ; then
+ PREPARAMS="$PREPARAMS $cflags"
+ fi
+ fi
+ done
+ # create build directory if requested
+ test -d "$BUILDDIR" || mkdir "$BUILDDIR"
+ SRCDIR="$PWD"
+ cd "$BUILDDIR"
+ echo "$PREPARAMS $CMAKE -DCMAKE_MODULE_PATH=\"$CMAKE_MODULE_PATH\" $CMAKE_PARAMS $CMAKE_FLAGS \"$SRCDIR\""
+ eval $PREPARAMS $CMAKE "-DCMAKE_MODULE_PATH=\"$CMAKE_MODULE_PATH\" $CMAKE_PARAMS $CMAKE_FLAGS \"$SRCDIR\"" || exit 1
+ else
+ PARAMS="$PARAMS ACLOCAL_AMFLAGS=\"$ACLOCAL_FLAGS\""
+ echo ./configure "$PARAMS"
+ # create build directory if requested
+ if test -n "$BUILDDIR"; then
+ test -d "$BUILDDIR" || mkdir "$BUILDDIR"
+ SRCDIR="$PWD"
+ cd "$BUILDDIR"
+ eval "$SRCDIR/configure" "$PARAMS" || exit 1
+ else
+ eval ./configure "$PARAMS" || exit 1
+ fi
+ fi
+ else
+ if test -f configure.in || test -f configure.ac; then
+ echo "ERROR: configure.[in|ac] found, but configure missing." >&2
+ echo "Did you forget to run autoconf?" >&2
+ echo "Perhaps you didn't update your project to" >&2
+ echo "the latest buildsystem changes (FS#382)." >&2
+ echo "If your project is under version control, please make sure" >&2
+ echo "you have a file stamp-vc in you top_srcdir." >&2
+ exit 1
+ fi
+ fi
+}
+
+run_default_make () {
+ test ! -d "$BUILDDIR" || cd "$BUILDDIR"
+ PARAMS="$CMD_FLAGS"
+ echo make "$PARAMS"
+ eval $MAKE "$PARAMS"
+}
+
+run_default_all () {
+ for cmd in vcsetup autogen configure make; do
+ eval echo "--- calling $cmd for \$NAME_${module} ---"
+ load_opts $cmd
+ run_$cmd
+ done
+}
+
+run_default_svn () {
+ if test -d .svn; then
+ PARAMS="$CMD_FLAGS"
+ eval svn "$PARAMS"
+ fi
+}
+
+run_default_git () {
+ if test -d .git; then
+ PARAMS="$CMD_FLAGS"
+ eval git "$PARAMS"
+ fi
+}
+
+###############################################
+###
+### main
+###
+
+onfailure() {
+ echo "Execution of $(basename "$0") terminated due to errors!" >&2
+ exit 1
+}
+
+usage () {
+ (
+ echo "Usage: $(basename "$0") [OPTIONS] COMMANDS [COMMAND-OPTIONS]"
+ echo ""
+ echo " Execute COMMANDS for all Dune modules found. All entries in the"
+ echo " DUNE_CONTROL_PATH variable are scanned recursively for Dune modules."
+ echo " If DUNE_CONTROL_PATH is empty, the current directory is scanned."
+ echo " Dependencies are controlled by the $CONTROL files."
+ echo ""
+ echo "OPTIONS:"
+ echo " -h, --help show this help"
+ echo " --debug enable debug output of this script"
+ echo " --use-cmake use cmake instead autotools for building"
+ echo " --module=mod only apply the actions on module mod"
+ echo " and all modules it depends on"
+ echo " --only=mod only apply the actions on module mod"
+ echo " and not the modules it depends on"
+ echo " --current only apply the actions on the current module,"
+ echo " the one whose source tree we are standing in"
+ echo " --resume resume a previous run (only consider the modules"
+ echo " not built successfully on the previous run)"
+ echo " --skipfirst skip the first module (use with --resume)"
+ echo " --opts=FILE load default options from FILE"
+ echo " (see dune-common/doc/example.opts)"
+ echo " --builddir=NAME make out-of-source builds in a subdir NAME."
+ echo " This directory is created inside each module."
+ echo " --[COMMAND]-opts=opts set options for COMMAND"
+ echo " (this is mainly useful for the 'all' COMMAND)"
+ echo "COMMANDS:"
+ echo " Colon-separated list of commands. Available commands are:"
+ printf " \`help'\tguess what :-)\n"
+ printf " \`print'\tprint the list of modules sorted after their dependencies\n"
+ printf " \`info'\tsame as \`print\', but including whether it is a dependency or suggestion\n"
+ for i in $COMMANDS; do
+ printf " \`$i'\t$(eval echo \$${i}_HELP)\n"
+ done
+ printf " \`export'\trun eval \`dunecontrol export\` to save the list of\n"
+ printf " \t\tdune.module files to the DUNE_CONTROL_PATH variable\n"
+ echo
+ ) >&2
+}
+
+# create the module list
+create_module_list() {
+ # try to get the resume file name from the options
+ if test -z "$RESUME_FILE" && test -n "$DUNE_OPTS_FILE"; then
+ export RESUME_FILE="$(eval . $DUNE_OPTS_FILE; eval echo \$RESUME_FILE)"
+ fi
+
+ if test "$RESUME_FLAG" = "yes" ; then
+ if ! test -s "$RESUME_FILE" ; then
+ echo "Error: No previous run to resume. Please make sure that the RESUME_FILE"
+ echo " is the name of a writeable file (currently it is '$RESUME_FILE')"
+ exit 1
+ fi
+
+ export MODULES=
+ RESUME="`cat "$RESUME_FILE"`"
+ for a in $RESUME ; do
+ export NAME_`fix_variable_name $a`="$a"
+ fix_and_assign MODULE "$a"
+ export SEARCH_MODULES="$SEARCH_MODULES $MODULE"
+ export ONLY="$ONLY $MODULE"
+ done
+ fi
+
+ find_modules_in_path
+ if test "x$ONLY" != x; then
+ export MODULES="$ONLY"
+ elif test "x$SEARCH_MODULES" != "x"; then
+ sort_modules $SEARCH_MODULES
+ else
+ sort_modules $MODULES
+ fi
+
+ if test "x$REVERSE_FLAG" = "xyes"; then
+ export MODULES="$REVERSEMODULES"
+ fi
+
+ if test "x$SKIPFIRST" = "xyes" ; then
+ export MODULES=`echo $MODULES " " | cut '--delimiter= ' --fields=2-`
+ fi
+ # warn about superseeded modules:
+ if test -n "$superseded_modules"; then
+ # sort moules list and make it unique.
+ superseded_modules=$(echo $superseded_modules | tr ' ' '\n'| sort -u)
+ echo >&2
+ echo "The following local modules do supersede the corresponding installed ones:" >&2
+ echo "$superseded_modules" >&2
+ echo >&2
+ fi
+}
+
+# print the module list
+print_module_list() {
+ DELIM=$1
+ shift
+ while test -n "$2"; do
+ echo -n "$(eval echo \$NAME_$1)$DELIM"
+ shift
+ done
+ echo -n "$(eval echo \$NAME_$1)"
+}
+
+trap onfailure EXIT
+
+# clear variables
+export SEARCH_MODULES=""
+export MODULES=""
+export ONLY=""
+export RESUME_FLAG=no
+export REVERSE_FLAG=no
+export SKIPFIRST=no
+
+# read environment variable USE_CMAKE
+export DUNE_USE_CMAKE="$(echo $USE_CMAKE)"
+
+# parse commandline parameters
+while test $# -gt 0; do
+ # get option
+ command=$1
+ option=$1
+
+ # get args
+ set +e
+ # stolen from configure...
+ # when no option is set, this returns an error code
+ arg=`expr "x$option" : 'x[^=]*=\(.*\)'`
+ set -e
+
+ # switch
+ case "$option" in
+ --opts=*)
+ if test "x$arg" = "x"; then
+ usage
+ echo "ERROR: Parameter for --opts is missing" >&2
+ echo >&2
+ exit 1;
+ fi
+ DUNE_OPTS_FILE=`canonicalname $arg`
+ if ! test -r "$DUNE_OPTS_FILE"; then
+ usage
+ echo "ERROR: could not read opts file \"$DUNE_OPTS_FILE\"" >&2
+ echo >&2
+ exit 1;
+ fi
+ ;;
+ --*-opts=*)
+ optcmd=`expr "x$option=" : 'x--\([^-]*\)-opts=.*'`
+ if is_command $optcmd; then
+ COMMAND=`echo $optcmd | tr '[:lower:]' '[:upper:]'`
+ export ${COMMAND}_FLAGS="$arg"
+ else
+ usage
+ echo "ERROR: unknown option \"$option\"" >&2
+ exit 1
+ fi
+ ;;
+ -h|--help)
+ command=help
+ break
+ ;;
+ -p|--print)
+ command=print
+ break
+ ;;
+ --module=*)
+ if test "x$arg" = "x"; then
+ usage
+ echo "ERROR: Parameter for --module is missing" >&2
+ echo >&2
+ exit 1;
+ fi
+ for a in `echo $arg | tr ',' ' '`; do
+ export NAME_`fix_variable_name $a`="$a"
+ fix_and_assign MODULE "$a"
+ export SEARCH_MODULES="$SEARCH_MODULES $MODULE"
+ done
+ ;;
+ --only=*)
+ if test "x$arg" = "x"; then
+ usage
+ echo "ERROR: Parameter for --only is missing" >&2
+ echo >&2
+ exit 1;
+ fi
+ for a in `echo $arg | tr ',' ' '`; do
+ export NAME_`fix_variable_name $a`="$a"
+ fix_and_assign MODULE "$a"
+ export SEARCH_MODULES="$SEARCH_MODULES $MODULE"
+ export ONLY="$ONLY $MODULE"
+ done
+ ;;
+ --builddir=*)
+ export DUNE_BUILDDIR=$arg
+ ;;
+ --no-builddir)
+ export DUNE_BUILDDIR=""
+ ;;
+ --skipversioncheck)
+ export SKIPVERSIONCHECK=yes
+ ;;
+ --current)
+ while ! test -f $CONTROL; do
+ cd ..
+ if test "$OLDPWD" = "$PWD"; then
+ echo "You are not inside the source tree of a DUNE module." >&2
+ exit -1
+ fi
+ done;
+ parse_control $PWD/$CONTROL
+ fix_and_assign MODULE "$module"
+ export SEARCH_MODULES="$SEARCH_MODULES $MODULE"
+ export ONLY="$ONLY $MODULE"
+ ;;
+ --resume)
+ export RESUME_FLAG="yes"
+ ;;
+ --reverse)
+ export REVERSE_FLAG="yes"
+ ;;
+ --skipfirst)
+ export SKIPFIRST=yes
+ ;;
+ --use-cmake|--cmake)
+ export DUNE_USE_CMAKE=yes
+ ;;
+ --no-cmake)
+ export DUNE_USE_CMAKE=no
+ ;;
+ --debug) true ;; # ignore this option, it is handled right at the beginning
+ --*)
+ usage
+ echo "ERROR: Unknown option \`$option'" >&2
+ echo >&2
+ exit 1
+ ;;
+ *)
+ break
+ ;;
+ esac
+
+ shift
+done
+
+extract_multiarch
+
+# create PKG_CONFIG_PATH for installed dune modules
+for i in $MULTIARCH_LIBDIR lib64 lib32 lib; do
+ if test -d "$PREFIX_DIR/$i/pkgconfig"; then
+ export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$PREFIX_DIR/$i/pkgconfig"
+ fi
+done
+
+# we assume there should be a command...
+if test "x$command" = "x"; then
+ usage
+ exit 1
+fi
+
+case "$command" in
+ print)
+ create_module_list
+ eval "print_module_list ' ' $MODULES"
+ echo >&2
+ ;;
+ info)
+ create_module_list
+ echo $SORTEDMODULES_INFO
+ ;;
+ export)
+ create_module_list
+ DUNE_CONTROL_PATH=""
+ for mod in $MODULES; do
+ path="$(eval echo \$PATH_$mod)"
+ name=$(eval echo \$NAME_$mod)
+ if test -f "$path/dune.module"; then
+ export DUNE_CONTROL_PATH="$DUNE_CONTROL_PATH:$path/dune.module"
+ else
+ if test -f "$path/lib/dunecontrol/$name/dune.module"; then
+ export DUNE_CONTROL_PATH="$DUNE_CONTROL_PATH:$path/lib/dunecontrol/$name/dune.module"
+ else
+ echo "ERROR: while creating list of dune.module files" >&2
+ echo " couldn't find dune.module file for $name in $path" >&2
+ echo >&2
+ exit 1
+ fi
+ fi
+ done
+ echo export DUNE_CONTROL_PATH=$(echo $DUNE_CONTROL_PATH | $SED -e 's/^://')
+ ;;
+ printdeps)
+ find_modules_in_path
+ if test "x$SEARCH_MODULES" == "x"; then
+ echo "ERROR: printdeps requires an explicit --module=... parameter" >&2
+ exit 1
+ fi
+ mainmod=`echo $SEARCH_MODULES`
+ name=`eval echo \\${NAME_$mainmod}`
+ echo "dependencies for $name"
+ ### DEPENDENCIES
+ sort_modules $mainmod
+ for mod in $SORTEDMODULES_DEPS; do
+ echo " $mod (required)"
+ done
+ for mod in $SORTEDMODULES_SUGS; do
+ echo " $mod (suggested)"
+ done
+ ;;
+ m4create)
+ find_modules_in_path
+ if test "x$SEARCH_MODULES" == "x"; then
+ echo "ERROR: m4create requires an explicit --module=... parameter" >&2
+ exit 1
+ fi
+ mainmod=`echo $SEARCH_MODULES`
+ eval mainmodpath="\$PATH_$mainmod"
+ fname="$mainmodpath/dependencies.m4"
+ name=`eval echo \\${NAME_$mainmod}`
+ version=`eval echo \\${VERS_$mainmod}`
+ maintainer=`eval echo \\${MAIN_$mainmod}`
+ # get dependencies
+ eval deps=\$DEPS_$mainmod
+ #initially remove leading space
+ deps=`echo "$deps" | $SED 's/^ *//'`
+ while test -n "$deps"; do
+ #the end of the name is marked either by space, opening paren
+ #or comma
+ depname="${deps%%[ (,]*}"
+ #remove the name and adjacent whitespace
+ deps=`echo "$deps" | $SED 's/^[^ (,]* *//'`
+ #check whether there is a dependency version
+ case "$deps" in
+ '('*) deps="${deps#(}"
+ depver="${deps%%)*}"
+ deps="${deps#*)}"
+ ;;
+ *) depver=
+ ;;
+ esac
+ #remove any leading whitespace or commas for te next iteration
+ deps=`echo "$deps" | $SED 's/^[, ]*//'`
+
+ requires="$requires $depname $depver "
+ done
+ # get suggestions
+ eval sugs=\$SUGS_$mainmod
+ #initially remove leading space
+ sugs=`echo "$sugs" | $SED 's/^ *//'`
+ while test -n "$sugs"; do
+ #the end of the name is marked either by space, opening paren
+ #or comma
+ sugsname="${sugs%%[ (,]*}"
+ #remove the name and adjacent whitespace
+ sugs=`echo "$sugs" | $SED 's/^[^ (,]* *//'`
+ #check whether there is a dependency version
+ case "$sugs" in
+ '('*) sugs="${sugs#(}"
+ sugsver="${sugs%%)*}"
+ sugs="${sugs#*)}"
+ ;;
+ *) sugver=
+ ;;
+ esac
+ #remove any leading whitespace or commas for te next iteration
+ sugs=`echo "$sugs" | $SED 's/^[, ]*//'`
+
+ suggests="$suggests $sugsname"
+ suggestsall="$suggestsall $sugsname $sugsver "
+ done
+ # ensure a version number
+ if test "x$version" = "x"; then version="0.0"; fi
+ echo "writing $fname"
+ echo " for $name $version $maintainer"
+ echo " requires $requires"
+ echo " suggests $suggestsall"
+ AC_MACRO_DIR="."
+ test ! -d m4 || AC_MACRO_DIR=m4
+ cat > "$fname" <<EOF
+# dependencies.m4 generated by dunecontrol
+
+m4_define([DUNE_AC_INIT],[
+ AC_INIT([$name], [$version], [$maintainer])
+ AM_INIT_AUTOMAKE([foreign 1.9 tar-pax])
+ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([no])])
+ AC_SUBST([DUNE_MOD_VERSION], [$version])
+ AC_SUBST([DUNE_MOD_NAME], [$name])
+ AC_SUBST([DUNE_MAINTAINER_NAME], ["$maintainer"])
+ DUNE_PARSE_MODULE_VERSION([$name], [$version])
+ REQUIRES="$requires"
+ AC_SUBST(REQUIRES, [$REQUIRES])
+ AC_CONFIG_MACRO_DIR([$AC_MACRO_DIR])
+])
+
+AC_DEFUN([DUNE_CHECK_MOD_DEPENDENCIES], [
+EOF
+ ### initialize AM_CONDITIONAL for suggestions that were not found
+ for name in $suggests; do
+ mod=$(fix_variable_name $name)
+ MOD=`echo $mod | tr [:lower:] [:upper:]`
+ if test "x$(eval echo \$HAVE_$mod)" = "x"; then
+ cat >> "$fname" <<EOF
+ ### add a conditional check for $name,
+ # just in case the module is not available at autogen time
+ AM_CONDITIONAL([HAVE_${MOD}], false)
+EOF
+ fi
+ done
+ ### ANALYSE MODULE
+ sort_modules $mainmod
+ ### DEPENDENCIES
+ for mod in $SORTEDMODULES_DEPS; do
+ name=`eval echo \\$NAME_$mod`
+ MOD=`echo $mod | tr [:lower:] [:upper:]`
+ cat >> "$fname" <<EOF
+ ### check dependency $name
+ # invoke checks required by this module
+ AC_REQUIRE([${MOD}_CHECKS])
+ # invoke check for this module
+ AC_REQUIRE([${MOD}_CHECK_MODULE])
+ if test x\$with_$mod = xno; then
+ AC_MSG_ERROR([could not find required module _dune_name])
+ fi
+EOF
+ done
+ ###
+ for mod in $SORTEDMODULES_SUGS; do
+ name=`eval echo \\$NAME_$mod`
+ MOD=`echo $mod | tr [:lower:] [:upper:]`
+ cat >> "$fname" <<EOF
+ ### check suggestion $name
+ # invoke checks required by this module
+ AC_REQUIRE([${MOD}_CHECKS])
+ # invoke check for this module
+ AC_REQUIRE([${MOD}_CHECK_MODULE])
+ if test x\$with_$mod = xno; then
+ AC_MSG_WARN([could not find suggested module _dune_name])
+ fi
+EOF
+ done
+ ###
+ # only test for the module if we really define our own checks
+ if test -d m4; then
+ mod=$mainmod
+ name=`eval echo \\$NAME_$mod`
+ MOD=`echo $mod | tr [:lower:] [:upper:]`
+ cat >> "$fname" <<EOF
+ ### invoke checks for $name
+ AC_REQUIRE([${MOD}_CHECKS])
+EOF
+ fi
+ cat >> "$fname" <<EOF
+])
+EOF
+ ;;
+ unexport)
+ echo export DUNE_CONTROL_PATH=""
+ ;;
+ help)
+ usage
+ ;;
+ *)
+ set +e
+ if test "x$USE_CMAKE" = "xno"; then
+ echo "$PREFIX_DIR" |$GREP "[ ]" >/dev/null
+ if test "$?" -eq "0"; then
+ echo "ERROR: The prefix directory path ($PREFIX_DIR) contains spaces. This is not"
+ echo " supported when using autotools."
+ echo " Either rename the path or activate CMake with --use-cmake switch."
+ exit 1
+ fi
+ fi
+ set -e
+ if test "$1" = "update"; then export SKIPVERSIONCHECK=yes; fi
+ check_commands "$@"
+ create_module_list
+ NAMES=""
+ BUILDMODULES=""
+ for mod in $MODULES; do
+ if test "$(eval echo \$INST_$mod)" != "yes"; then
+ NAMES="$NAMES$(eval echo \$NAME_$mod) "
+ BUILDMODULES="$BUILDMODULES$mod "
+ fi
+ done
+ echo "--- going to build $NAMES ---"
+ if test -n "$RESUME_FILE"; then
+ # write all modules to the resume file
+ for mod in $MODULES ; do
+ echo "$mod"
+ done > "$RESUME_FILE"
+ fi
+
+ for mod in $BUILDMODULES; do
+ build_module "$mod" "$@"
+
+ if test -n "$RESUME_FILE"; then
+ # remove the current module from the resume file
+ modules_togo=`cat "$RESUME_FILE"`
+ for mod_togo in $modules_togo ; do
+ if test "$mod_togo" != "$mod" ; then
+ echo "$mod_togo"
+ fi
+ done > "$RESUME_FILE"
+ fi
+ done
+ echo "--- done ---"
+ ;;
+esac
+
+trap - EXIT
--- /dev/null
+#!/bin/sh
+
+if [ "x$DEBUG" = "xyes" ]; then
+ set -x
+fi
+
+DOXYOUT=${1:-doc/doxygen/Doxyfile.in}
+OUTDIR=`dirname "$DOXYOUT"`
+DOXYDIR="doc/doxygen/"
+
+find_doxystyle()
+{
+ for i in "`dirname "$0"`/../doc/doxygen/Doxystyle" "`dirname "$0"`/../share/dune-common/doc/doxygen/Doxystyle"; do
+ if [ -f "$i" ]; then
+ export DOXYSTYLE="$i"
+ return 0
+ fi
+ done
+ return 1
+}
+
+test_doxylocal()
+{
+ while [ -n "$1" ]; do
+ if [ -f "$1/dune.module" ]; then
+ return 0
+ fi
+ shift
+ done
+ return 1
+}
+
+parse_doxyfile()
+{
+ # Doxylocal is used _as is_
+ if [ "$2" = "Doxylocal" ]; then
+ cat $1/$DOXYDIR/$2
+ return
+ fi
+
+ local FILE=$1/$DOXYDIR/$2
+ local FOUND=0
+ local line
+
+ # find lines that match the pattern
+ set `grep -n '^ *\(INPUT\|EXAMPLE_PATH\|IMAGE_PATH\|PREDEFINED\|EXCLUDE\|EXAMPLE_PATTERNS\) *[+=]' $FILE | cut -d: -f1`
+
+ # search lines in $@ and proceeding lines
+ grep -n . $FILE |
+ sed -e 's/\\/\\\\/g' |
+ while read line; do
+ if [ "${line%%:*}" -eq "${1:-0}" ]; then
+ FOUND=1
+ # subst = by += if necessary
+ start="${line%%=*}"
+ case "$start" in
+ *+) ;;
+ *) line="$start+=${line#*=}" ;;
+ esac
+ shift
+ fi
+ if [ $FOUND -eq 1 ]; then
+ echo "$line"
+ else
+ continue
+ fi
+ # check for trailing '\'
+ case "$line" in
+ *\\) FOUND=1 ;;
+ *) FOUND=0 ;;
+ esac
+ done | sed -e 's/^[0-9]*://'
+}
+
+parse_doxylocal()
+{
+ if echo $1 | grep -q "^/"; then
+ srcdir=$1/$DOXYDIR
+ top_srcdir=$1
+ parse_doxyfile $1 $2 | sed -e "s!@\(abs_\)*srcdir@!$srcdir!" -e "s!@\(abs_\)*top_srcdir@!$top_srcdir!";
+ else
+ parse_doxyfile $1 $2
+ fi
+}
+
+get_module_name()
+{
+ grep "^Module:" $1/dune.module | sed -e 's/^Module: *//'
+}
+
+generate_doxyout()
+{
+ echo "Generating $DOXYOUT from "
+ echo " global style"
+ cat "$DOXYSTYLE" > "$DOXYOUT"
+ while [ -n "$1" ]; do
+ for DOXY in Doxylocal Doxyfile.in Doxyfile; do
+ if [ "$1/$DOXYDIR/$DOXY" -ef "$DOXYOUT" ]; then continue; fi
+ if [ -f "$1/$DOXYDIR/$DOXY" ]; then
+ echo " and `get_module_name $1` config"
+ parse_doxylocal $1 $DOXY >> $DOXYOUT
+ break
+ fi
+ done
+ shift
+ done
+ echo " ... done"
+}
+
+generate_doxylocal()
+{
+ echo "Generating $DOXYOUT from "
+ for DOXY in Doxyfile.in Doxyfile; do
+ if [ -f "$1/$DOXYDIR/$DOXY" ]; then
+ echo " `get_module_name .` $DOXY"
+ parse_doxylocal . $DOXY > $DOXYOUT
+ break
+ fi
+ done
+ echo " ... done"
+}
+
+# make sure we are in dune module
+if ! [ -f dune.module ]; then
+ echo "Error: dunedoxynize must be called from the top_srcdir of your module"
+ exit 1
+fi
+
+# don't do anything if we have old style Doxyfile or Doxyfile.in, but no Doxylocal
+if [ $# -eq 0 ] && ! [ -f "$DOXYDIR/Doxylocal" ]; then
+ for DOXY in Doxyfile.in Doxyfile; do
+ if [ -f "$DOXYDIR/$DOXY" ]; then
+ echo "Warning: module still uses handwritten $DOXY"
+ echo " You can transform it to an initial Doxylocal by calling"
+ echo " dune-common/bin/dunedoxynize doc/doxygen/Doxylocal ."
+ echo " in the top source directory of this module"
+ exit 0
+ fi
+ done
+ exit 0
+fi
+
+# quit if your module doesn't have any documentation
+if ! [ -d "$OUTDIR" ]; then
+ if [ $# -eq 0 ]; then
+ exit 0
+ else
+ echo "Error: output directory $OUTDIR does not exist."
+ exit 0
+ fi
+fi
+
+# search for doxygen style
+if ! find_doxystyle; then
+ echo "Error: dunedoxynize global style not found"
+ exit 1
+fi
+
+# drop the parameter of the output file
+if [ $# -gt 0 ]; then
+ shift
+fi
+
+# make sure that there is at least one Doxylocal file
+if ! test_doxylocal "${@:-.}" && [ $# -gt 0 ]; then
+ echo "Error: you didn't supply any valid Doxylocal file"
+ exit 1
+fi
+
+if [ "`basename $DOXYOUT`" = "Doxylocal" ]; then
+ generate_doxylocal "${@:-.}"
+else
+ generate_doxyout "${@:-.}"
+fi
--- /dev/null
+#!/bin/bash
+
+#
+# TODO:
+#
+# * In case of an installed Dune, it should not be necessary to pass the
+# dune-common dir to autogen.sh.
+# * Check module names entered as dependencies.
+
+set -e
+
+canonicalname(){
+ if test $# -ne 1; then
+ echo Usage: canonicalname path >&2
+ return 1
+ fi
+ file="`eval echo $1`" # expand ~
+ if test ! -e "$file"; then
+ echo $file: file not found >&2
+ return 1
+ fi
+ # if this is a symlink, then follow the symlink
+ if test -L "$file"; then
+ fdir="`dirname \"$file\"`"
+ flink="`readlink \"$file\"`"
+ if test -e "$flink"; then
+ # these are absolute links, or links in the CWD
+ canonicalname "$flink"
+ else
+ canonicalname "$fdir/$flink"
+ fi
+ else
+ # if this is a file, then remember the filename and
+ # canonicalize the directory name
+ if test -f "$file"; then
+ fdir="`dirname \"$file\"`"
+ fname="`basename \"$file\"`"
+ fdir="`canonicalname \"$fdir\"`"
+ echo "$fdir/$fname"
+ fi
+ # if this is a directory, then create an absolute
+ # directory name and we are done
+ if test -d "$file"; then
+ (cd "$file"; pwd)
+ fi
+ fi
+}
+
+canonicalpath(){
+ if test $# -ne 1; then
+ echo Usage: canonicalpath path >&2
+ return 1
+ fi
+ dirname "$(canonicalname "$1")"
+}
+
+pkg_config_dependencies(){
+ if test $# -ne 1; then
+ echo Usage: pkg_config_dependencies name >&2
+ return 1
+ fi
+ name="$1"
+ depends="`pkg-config --variable=DEPENDENCIES $name| sed -e 's/,/ /g'`"
+ for pkg in $depends; do
+ depends="$depends `pkg_config_dependencies $pkg`"
+ done
+ echo $depends
+}
+
+modulesexist(){
+ allfound=0
+
+ for dep in $1; do
+ found=0
+ for module in $2; do
+ if [ "$dep" = "$module" ]; then
+ found=1
+ break
+ fi
+ done
+ if [ "$found" = "0" ]; then
+ # Module not found in list, try pkg-config
+ pkg-config $module &> /dev/null
+ found=$?
+ fi
+ if [ "$found" = "0" ]; then
+ echo "ERROR:">&2
+ echo "Module with name $dep was not found" >&2
+ echo "Did you forget to specify it's location" >&2
+ echo "in the DUNE_CONTROL_PATH variable?">&2
+ echo >&2
+ allfound=1
+ fi
+ done
+ return $allfound
+}
+
+make_unique(){
+ if [ "$#" = "1" ]; then
+ # take first word
+ for exclude_word in $1; do
+ break;
+ done
+ make_unique $exclude_word "$1" 0
+ else
+ local exclude_word="$1"
+ local words="$2"
+ local pos="$3"
+ local length=0
+ local i=0
+ local new_words=""
+ local cur=0
+ for word in $words; do
+ if [ $i -le $pos ]; then
+ i=$((i+1))
+ length=$((length+1))
+ new_words="$new_words $word"
+ continue
+ fi
+ if [ "$word" != "$exclude_word" ]; then
+ new_words="$new_words $word"
+ if [ "$((length-1))" = "$pos" ]; then
+ next_word="$word"
+ fi
+ length=$((length+1))
+ fi
+ done
+ if [ "$pos" -lt "$length" ]; then
+ # process next word
+ make_unique "$next_word" "$new_words" $((pos+1))
+ else
+ export UNIQUE_WORDS="$new_words"
+ fi
+ fi
+}
+
+echo
+echo == Dune project/module generator ==
+echo
+echo duneproject will assist you in the creation of a new Dune application.
+echo During this process a new directory with the name of your project will be
+echo created. This directory will hold all configuration and Makefiles and a
+echo simple example application.
+echo
+
+################## FIND AVAILABLE MODULES ##################
+
+. "$(canonicalpath $0)/../lib/dunemodules.lib"
+
+export PREFIX_DIR="`canonicalpath "$0"`/.."
+
+extract_multiarch_pkg_config_path
+
+# search for modules, both installed and src modules
+find_modules_in_path
+
+# sort modules to remove duplicates
+sort_modules $FOUND_MODULES
+FOUND_MODULES=$MODULES
+
+# get the real module names
+MODULES=""
+for i in $FOUND_MODULES; do
+ mod=$(eval echo \$NAME_$i)
+ MODULES="$MODULES$mod "
+done
+
+if [ "$MODULES" = "" ]; then
+ echo "ERROR:">&2
+ echo " No dune modules were found!">&2
+ echo " Did you forget to specify the places where ">&2
+ echo " you installed your modules in the ">&2
+ echo " DUNE_CONTROL_PATH environment variable">&2
+ echo " and adjusted the PKG_CONFIG_PATH environment">&2
+ echo " accordingly?" >&2
+ exit 1;
+fi
+
+################## READ CMDLINE OPTIONS ##########
+PROJECT="$1"
+DEPENDENCIES="$2"
+VERSION="$3"
+MAINTAINER="$4"
+
+################## READ OPTIONS ##################
+
+while [ "$DATACORRECT" != "y" -a "$DATACORRECT" != "Y" ]; do
+ while [ -z $PROJECT ]; do
+ read -p "1) Name of your new Project? (e.g.: dune-grid): " PROJECT
+ if echo "$MODULES" | grep -q ^$PROJECT$; then
+ read -p " A module named $PROJECT already exists. Continue anyway? [y/N] " CONT
+ if test x$DELETE = xy -o x$DELETE = xY; then
+ PROJECT=""
+ fi
+ elif echo "$PROJECT" | grep -q "\."; then
+ echo "The Name contains a dot (.) which is not allowed."
+ PROJECT=""
+ fi
+ done
+ MODULE="$PROJECT"
+
+ DEPOK=1
+
+ while [ "$DEPOK" != 0 ]; do
+ echo "2) Which modules should this module depend on?"
+ echo " Following modules are found:"
+ echo " $MODULES"
+# for i in $MODULES; do echo -n " $i"; done
+# echo ""
+ while [ -z "$DEPENDENCIES" ]; do
+ read -p " Enter space separated list: " DEPENDENCIES
+ done
+ set +e
+ modulesexist "$DEPENDENCIES" "$MODULES"
+ DEPOK=$?
+ set -e
+ if [ "$DEPOK" != 0 ]; then
+ DEPENDENCIES=""
+ fi
+ done
+
+ while [ -z $VERSION ]; do
+ read -p "3) Project/Module version? " VERSION
+ done
+ while [ -z "$MAINTAINER" ]; do
+ read -p "4) Maintainers email address? " MAINTAINER
+ done
+
+ echo
+ echo "creating Project \"$PROJECT\", version $VERSION "
+ echo "which depends on \"$DEPENDENCIES\""
+ echo "with maintainer \"$MAINTAINER\""
+ read -p "Are these informations correct? [y/N] " DATACORRECT
+
+ # reset data if necessary
+ if [ "$DATACORRECT" != "y" -a "$DATACORRECT" != "Y" ]; then
+ PROJECT=""
+ DEPENDENCIES=""
+ VERSION=""
+ MAINTAINER=""
+ fi
+done
+
+echo
+echo "A sample code $MODULE.cc is generated in the \"$PROJECT\" directory."
+echo "Look at the README and dune.module files there."
+echo "Now you can run the dunecontrol script which will setup the new module."
+echo "Sometimes you may have to tweak configure.ac a bit."
+
+if test -d $PROJECT; then
+ echo WARNING:
+ echo "A directory with the name $PROJECT already exists."
+ echo "Do you want to continue anyway?"
+ read -p "Type Y to overwrite the old directory, N to abort. [y/N] " DELETE
+ if test x$DELETE != xy -a x$DELETE != xY; then
+ echo Abort...
+ exit 1
+ fi
+ rm -rf "$PROJECT"
+fi
+mkdir "$PROJECT"
+
+################## dune.module ##################
+cat > "$PROJECT/dune.module" <<C_DELIM
+################################
+# Dune module information file #
+################################
+
+#Name of the module
+Module: $MODULE
+Version: $VERSION
+Maintainer: $MAINTAINER
+#depending on
+Depends: $DEPENDENCIES
+C_DELIM
+
+################## CONFIGURE.AC ##################
+
+## Create the parameters passed to DUNE_CHECK_ALL
+
+# save module list of dunemodules.inc
+save_MODULES=$MODULES
+for name in $DEPENDENCIES; do
+ mod="`fix_variable_name $name`"
+ if test "x$(eval echo \$HAVE_$mod)" != "x"; then
+ # found via dunemodules.inc
+ sort_modules "$mod"
+ for mod in $MODULES; do
+ M_DEPS="$M_DEPS $(eval echo \$NAME_$mod)"
+ done
+ MODULES=$save_MODULES
+ else
+ # found via pkg-config
+ M_DEPS="`pkg_config_dependencies $name` $name"
+ fi
+ for dep in $M_DEPS; do
+ CHECK="$CHECK [$dep]"
+ done
+done
+set +x
+make_unique "$CHECK"
+
+# insert , between modules
+j=0
+for dep in $UNIQUE_WORDS; do
+if [ "$j" = "0" ]; then
+ CHECK="$dep"
+ j=1
+ else
+ CHECK="$CHECK, $dep"
+ fi
+done
+
+echo "------------------------------------------"
+echo "writing initial files:"
+
+# complete module name with _ instead of - to not confuse automake
+fix_and_assign CMODULE $MODULE
+# module name without suffix "dune-"
+NAME=`echo $PROJECT | sed -e 's/dune[_-]//'`
+# $NAME with _ instead of - to not confuse automake
+NAME_=`echo $NAME | tr '-' '_'`
+# module name in uppercase with _ instead of -
+UNAME=`echo $PROJECT | tr '-' '_' | sed 's/\(.*\)/\U\1/'`
+################## CONFIGURE.AC ##################
+echo "- $PROJECT/configure.ac"
+cat > "$PROJECT/configure.ac" <<C_DELIM
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+AC_PREREQ([2.62])
+DUNE_AC_INIT # gets module version from dune.module file
+AC_CONFIG_SRCDIR([src/$CMODULE.cc])
+AC_CONFIG_HEADERS([config.h])
+
+# we need no more than the standard DE-stuff
+# this module depends on $DEPENDENCIES
+# this implies checking for $CHECK
+DUNE_CHECK_ALL
+
+# implicitly set the Dune-flags everywhere
+AC_SUBST(AM_CPPFLAGS, \$DUNE_CPPFLAGS)
+AC_SUBST(AM_LDFLAGS, \$DUNE_LDFLAGS)
+LIBS="\$DUNE_LIBS"
+
+AC_CONFIG_FILES([
+ Makefile
+ src/Makefile
+ cmake/Makefile
+ cmake/modules/Makefile
+ doc/Makefile
+ doc/doxygen/Makefile
+ doc/doxygen/Doxyfile
+ dune/Makefile
+ dune/$NAME/Makefile
+ m4/Makefile
+ $MODULE.pc
+])
+AC_OUTPUT
+# finally print the summary information
+DUNE_SUMMARY_ALL
+C_DELIM
+
+################## README ##################
+echo "- $PROJECT/README"
+cat > "$PROJECT/README" <<R_DELIM
+Preparing the Sources
+=========================
+
+Additional to the software mentioned in README you'll need the
+following programs installed on your system:
+
+ automake >= 1.9
+
+ autoconf >= 2.62
+
+ libtool
+
+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.
+
+On your project and all uninstalled DUNE source modules found the script
+will then calls the GNU autoconf/automake to create a ./configure-script
+and the Makefiles. Afterwards that configure script will be called and the
+modules will be build using make all
+
+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
+defining three variables:
+
+AUTOGEN_FLAGS flags passed to autogen
+CONFIGURE_FLAGS flags passed to configure
+MAKE_FLAGS flags passed to make
+
+An example options file might look like this:
+
+#use this options to autogen, configure and make if no other options are given
+AUTOGEN_FLAGS="--ac=2.50 --ac=1.8" #Forces automake 2,50 and autoconf 1.8
+CONFIGURE_FLAGS="CXX=g++-3.4 --prefix=/install/path" #force g++-3.4 as compiler
+MAKE_FLAGS=install #Per default run make install instead of simply make
+
+If you save this information into example.opts you can path the opts file to
+dunecontrol via the --opts option, e. g.
+
+ dunecontrol --opts=example.opts all
+
+To get a full list of available configure flags just run
+
+ dunecontrol configure --help
+
+after running at least
+ dunecontrol autogen
+
+More info
+---------
+
+See
+
+ dunecontrol --help
+
+for further options.
+
+
+The full build-system is described in the dune-common/doc/buildsystem (SVN version) or under share/doc/dune-common/buildsystem if you installed DUNE!
+
+\$Id$
+
+R_DELIM
+
+################## MAKEFILE.AM ##################
+DISTCHECK_CONFIGURE_FLAGS=
+for name in $DEPENDENCIES; do
+ capital=`echo $name | tr '[a-z-]' '[A-Z_]'`
+ DISTCHECK_CONFIGURE_FLAGS=$DISTCHECK_CONFIGURE_FLAGS"--with-${name}=\$(${capital}_ROOT) "
+done
+echo "- $PROJECT/Makefile.am"
+cat> "$PROJECT/Makefile.am" << M_DELIM
+# \$Id$
+
+# we need the module file to be able to build via dunecontrol
+EXTRA_DIST = dune.module \\
+ CMakeLists.txt \\
+ config.h.cmake
+
+SUBDIRS = src m4 dune doc cmake
+
+if BUILD_DOCS
+# TODO: set up documentation tree automatically
+#SUBDIRS += doc
+endif
+
+# don't follow the full GNU-standard
+# we need automake 1.9 or newer
+AUTOMAKE_OPTIONS = foreign 1.9
+
+# pass most important options when "make distcheck" is used
+DISTCHECK_CONFIGURE_FLAGS = $DISTCHECK_CONFIGURE_FLAGS CXX="\$(CXX)" CC="\$(CC)"
+
+include \$(top_srcdir)/am/top-rules
+include \$(top_srcdir)/am/global-rules
+
+# Generate package configuration files for finding
+# installed modules with CMake
+include \$(top_srcdir)/am/cmake-pkg-config
+
+M_DELIM
+
+################## CMakeLists.txt ##################
+echo " - $PROJECT/CMakeLists.txt"
+cat> "$PROJECT/CMakeLists.txt" << M_DELIM
+cmake_minimum_required(VERSION 2.8.6)
+project($PROJECT 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()
+
+add_subdirectory("src")
+add_subdirectory("m4")
+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)
+M_DELIM
+
+################## STAMP-VC ##################
+echo "- $PROJECT/stamp-vc"
+echo 'A stamp file to signify that this directory comes from a version control system, not an unpacked tarball' > $PROJECT/stamp-vc
+
+################## PROJECT.PC.IN ##################
+echo "- $PROJECT/$MODULE.pc.in"
+cat> "$PROJECT/$MODULE.pc.in" << CC_DELIM
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+CXX=@CXX@
+CC=@CC@
+DEPENDENCIES=@REQUIRES@
+
+Name: @PACKAGE_NAME@
+Version: @VERSION@
+Description: $MODULE module
+URL: http://dune-project.org/
+Requires: ${DEPENDENCIES}
+Libs: -L\${libdir}
+Cflags: -I\${includedir}
+CC_DELIM
+echo " Please remember to update your $PROJECT/$MODULE.pc.in,"
+echo " Description and URL are missing right now."
+
+################# config.h.cmake #####################
+
+echo "- $PROJECT/config.h.cmake"
+cat> "$PROJECT/config.h.cmake" <<EOF
+/* begin $NAME
+ 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 $PROJECT */
+#define ${UNAME}_VERSION "@${UNAME}_VERSION@"
+
+/* Define to the major version of $PROJECT */
+#define ${UNAME}_VERSION_MAJOR @${UNAME}_VERSION_MAJOR@
+
+/* Define to the minor version of $PROJECT */
+#define ${UNAME}_VERSION_MINOR @${UNAME}_VERSION_MINOR@
+
+/* Define to the revision of $PROJECT */
+#define ${UNAME}_VERSION_REVISION @${UNAME}_VERSION_REVISION@
+
+/* end $NAME
+ Everything below here will be overwritten
+*/
+EOF
+## done
+
+###############################################################
+################## The source subdirectory ####################
+###############################################################
+
+mkdir "$PROJECT/src"
+
+################## src/CMakeLists.txt ##################
+
+echo "- $PROJECT/src/CMakeLists.txt"
+cat> "$PROJECT/src/CMakeLists.txt" << M_DELIM
+
+add_executable("${CMODULE}" ${CMODULE}.cc)
+target_link_dune_default_libraries("${CMODULE}")
+
+M_DELIM
+
+################## src/MAKEFILE.AM ##################
+
+echo "- $PROJECT/src/Makefile.am"
+cat> "$PROJECT/src/Makefile.am" << M_DELIM
+
+SUBDIRS =
+
+noinst_PROGRAMS = ${CMODULE}
+
+${CMODULE}_SOURCES = $CMODULE.cc
+
+${CMODULE}_CPPFLAGS = \$(AM_CPPFLAGS) \\
+ \$(DUNEMPICPPFLAGS) \\
+ \$(UG_CPPFLAGS) \\
+ \$(AMIRAMESH_CPPFLAGS) \\
+ \$(ALBERTA_CPPFLAGS) \\
+ \$(ALUGRID_CPPFLAGS)
+# The libraries have to be given in reverse order (most basic libraries
+# last). Also, due to some misunderstanding, a lot of libraries include the
+# -L option in LDFLAGS instead of LIBS -- so we have to include the LDFLAGS
+# here as well.
+${CMODULE}_LDADD = \\
+ \$(DUNE_LDFLAGS) \$(DUNE_LIBS) \\
+ \$(ALUGRID_LDFLAGS) \$(ALUGRID_LIBS) \\
+ \$(ALBERTA_LDFLAGS) \$(ALBERTA_LIBS) \\
+ \$(AMIRAMESH_LDFLAGS) \$(AMIRAMESH_LIBS) \\
+ \$(UG_LDFLAGS) \$(UG_LIBS) \\
+ \$(DUNEMPILIBS) \\
+ \$(LDADD)
+${CMODULE}_LDFLAGS = \$(AM_LDFLAGS) \\
+ \$(DUNEMPILDFLAGS) \\
+ \$(UG_LDFLAGS) \\
+ \$(AMIRAMESH_LDFLAGS) \\
+ \$(ALBERTA_LDFLAGS) \\
+ \$(ALUGRID_LDFLAGS) \\
+ \$(DUNE_LDFLAGS)
+
+# don't follow the full GNU-standard
+# we need automake 1.9
+AUTOMAKE_OPTIONS = foreign 1.9
+
+# pass most important options when "make distcheck" is used
+DISTCHECK_CONFIGURE_FLAGS = $DISTCHECK_CONFIGURE_FLAGS CXX="\$(CXX)" CC="\$(CC)"
+
+EXTRA_DIST = CMakeLists.txt
+
+include \$(top_srcdir)/am/global-rules
+
+M_DELIM
+
+################## PROJECT.CC ##################
+echo "- $PROJECT/src/$CMODULE.cc"
+cat> "$PROJECT/src/$CMODULE.cc" << CC_DELIM
+#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 ${PROJECT}." << 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;
+ }
+}
+CC_DELIM
+
+################## M4/MAKEFILE ####################
+mkdir "$PROJECT/m4"
+echo "- $PROJECT/m4/Makefile.am"
+cat> "$PROJECT/m4/Makefile.am" << CC_DELIM
+M4FILES = $MODULE.m4
+
+aclocaldir = \$(datadir)/dune/aclocal
+aclocal_DATA = \$(M4FILES)
+
+EXTRA_DIST = \$(M4FILES) CMakeLists.txt
+
+include \$(top_srcdir)/am/global-rules
+CC_DELIM
+
+
+echo "- $PROJECT/m4/CMakeLists.txt"
+cat> "$PROJECT/m4/CMakeLists.txt" << CC_DELIM
+
+install(PROGRAMS $MODULE.m4 DESTINATION \${CMAKE_INSTALL_DATAROOTDIR}/dune/aclocal)
+
+CC_DELIM
+
+################## M4/PROJECT.M4 ####################
+M4_MODULE=`echo $MODULE | tr '[a-z-]' '[A-Z_]'`
+echo "- $PROJECT/m4/$MODULE.m4"
+cat> "$PROJECT/m4/$MODULE.m4" << CC_DELIM
+dnl -*- autoconf -*-
+# Macros needed to find $MODULE and dependent libraries. They are called by
+# the macros in \${top_src_dir}/dependencies.m4, which is generated by
+# "dunecontrol autogen"
+
+# Additional checks needed to build $MODULE
+# This macro should be invoked by every module which depends on $MODULE, as
+# well as by $MODULE itself
+AC_DEFUN([${M4_MODULE}_CHECKS])
+
+# Additional checks needed to find $MODULE
+# This macro should be invoked by every module which depends on $MODULE, but
+# not by $MODULE itself
+AC_DEFUN([${M4_MODULE}_CHECK_MODULE],
+[
+ DUNE_CHECK_MODULES([$MODULE],[$NAME/$NAME.hh])
+])
+CC_DELIM
+
+
+################################################################
+################## The headers subdirectory ####################
+################################################################
+
+echo "- $PROJECT/dune/$NAME"
+mkdir "$PROJECT/dune"
+mkdir "$PROJECT/dune/$NAME"
+
+################## dune/Makefile.am ####################
+echo "- $PROJECT/dune/Makefile.am"
+cat> $PROJECT/dune/Makefile.am <<EOF
+SUBDIRS = $NAME
+
+EXTRA_DIST = CMakeLists.txt
+
+include \$(top_srcdir)/am/global-rules
+EOF
+
+echo "- $PROJECT/dune/CMakeLists.txt"
+cat> $PROJECT/dune/CMakeLists.txt <<EOF
+add_subdirectory($NAME)
+EOF
+
+
+################## dune/$NAME/Makefile.am ##############
+echo "- $PROJECT/dune/$NAME/Makefile.am"
+cat> $PROJECT/dune/$NAME/Makefile.am <<EOF
+${NAME_}includedir = \$(includedir)/dune/${NAME}
+${NAME_}include_HEADERS = ${NAME}.hh
+
+EXTRA_DIST = CMakeLists.txt
+
+include \$(top_srcdir)/am/global-rules
+EOF
+
+echo "- $PROJECT/dune/$NAME/CMakeLists.txt"
+cat> $PROJECT/dune/$NAME/CMakeLists.txt <<EOF
+#install headers
+install(FILES ${NAME}.hh DESTINATION include/dune/$NAME)
+
+EOF
+
+################## dune/$NAME/$NAME.hh #################
+echo "- $PROJECT/dune/$NAME/$NAME.hh"
+cat> $PROJECT/dune/$NAME/$NAME.hh <<EOF
+#ifndef $UNAME.hh
+#define $UNAME.hh
+
+// add your classes here
+
+#endif // $UNAME.hh
+EOF
+
+
+###############################################################
+################## The doc subdirectory ####################
+###############################################################
+
+mkdir "$PROJECT/doc"
+
+################## doc/Makefile.am ####################
+echo "- $PROJECT/doc/Makefile.am"
+cat> "$PROJECT/doc/Makefile.am" << CC_DELIM
+
+SUBDIRS = doxygen
+CURDIR = doc
+BASEDIR = ..
+
+# add list of html files to generate from wml
+PAGES=
+
+docdir=\$(datadir)/doc/${PROJECT}
+
+EXTRA_DIST = CMakeLists.txt
+
+include \$(top_srcdir)/am/webstuff
+include \$(top_srcdir)/am/global-rules
+CC_DELIM
+
+
+echo "- $PROJECT/doc/CMakeLists.txt"
+cat> "$PROJECT/doc/CMakeLists.txt" << CC_DELIM
+add_subdirectory("doxygen")
+CC_DELIM
+
+###############################################################
+############### The doc/doxygen subdirectory ##################
+###############################################################
+
+mkdir "$PROJECT/doc/doxygen"
+
+
+#################### basic Doxylocal ##########################
+
+echo "- $PROJECT/doc/doxygen/Doxylocal"
+if [ "x`which doxygen`" == "x" ]; then
+ echo "Doxygen is not installed! Your documentation will not work without."
+fi
+# Where to search and which files to use
+cat> $PROJECT/doc/doxygen/Doxylocal << CC_DELIM
+# 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/$NAME/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/$NAME/pics
+
+CC_DELIM
+
+################# doc/doxygen/Makefile.am #####################
+
+echo "- $PROJECT/doc/doxygen/Makefile.am"
+cat> "$PROJECT/doc/doxygen/Makefile.am" << CC_DELIM
+
+BASEDIR=../..
+CURDIR=doc/doxygen
+
+EXTRA_DIST = CMakeLists.txt
+
+include \$(top_srcdir)/am/doxygen
+include \$(top_srcdir)/am/global-rules
+
+CC_DELIM
+
+################# doc/doxygen/CMakeLists.txt #####################
+
+echo "- $PROJECT/doc/doxygen/CMakeLists.txt"
+cat> "$PROJECT/doc/doxygen/CMakeLists.txt" << CC_DELIM
+# shortcut for creating the Doxyfile.in and Doxyfile
+add_doxygen_target()
+CC_DELIM
+
+
+############### The cmake subdirectory ##################
+#########################################################
+
+mkdir "$PROJECT/cmake"
+
+################# cmake/Makefile.am #####################
+
+echo "- $PROJECT/cmake/Makefile.am"
+cat> "$PROJECT/cmake/Makefile.am" <<EOF
+SUBDIRS = modules
+
+include \$(top_srcdir)/am/global-rules
+EOF
+
+############### The cmake subdirectory ##################
+#########################################################
+
+mkdir "$PROJECT/cmake/modules"
+
+################# cmake/modules/Makefile.am #####################
+macroname=""
+for i in $(echo $PROJECT| sed 's/-/ /g'); do
+ firstchar=$(echo $i | sed 's/\(.\).*/\1/')
+ macroname=$macroname$(echo $firstchar | tr '[a-z]' '[A-Z]')$(echo $i | sed 's/.\(.*\)/\1/')
+done
+macroname="$macroname""Macros.cmake"
+
+echo "- $PROJECT/cmake/modules/Makefile.am"
+cat> "$PROJECT/cmake/modules/Makefile.am" <<EOF
+MODULES = $macroname
+modulesdir = \$(datadir)/dune/cmake/modules
+dist_modules_DATA = \${MODULES}
+
+include \$(top_srcdir)/am/global-rules
+EXTRA_DIST = CMakeLists.txt
+EOF
+
+################# cmake/modules/Makefile.am #####################
+
+echo "- $PROJECT/cmake/modules/CMakeLists.txt"
+cat> "$PROJECT/cmake/modules/CMakeLists.txt" <<EOF
+set(modules "$macroname")
+
+install(FILES \${modules} DESTINATION \${DUNE_INSTALL_MODULEDIR})
+EOF
+
+################# cmake/modules/$macroname #####################
+
+echo "- $PROJECT/cmake/modules/$macroname"
+cat> "$PROJECT/cmake/modules/$macroname" <<EOF
+# File for module specific CMake tests.
+EOF
+
+
+################# stamp-regenerate-config-h #####################
+
+echo "- $PROJECT/stamp-regenerate-config-h"
+touch $PROJECT/stamp-regenerate-config-h
+echo
+echo "done."
+echo "------------------------------------------"
+echo "For further details read the Dune Buildsystem-Howto:"
+echo "http://www.dune-project.org/doc/buildsystem/buildsystem.pdf"
+
--- /dev/null
+#!/bin/sh
+# dune-git-whitespace-hook
+# DO NOT TOUCH THE PRECEDING LINE
+# It is used by dunecontrol to enable automatic updates of the whitespace hook
+
+# DUNE pre-commit hook to enforce whitespace policy
+# This hook prevents adding lines with trailing whitespace and or tab characters
+# in line indentation for certain files (see the TRAILING_WHITESPACE_DEFAULT and
+# TAB_IN_INDENT_DEFAULT variables below for the default sets of files that will
+# be checked).
+# You can tell the hook which files should be inspected by setting the Git
+# configuration variables "hooks.whitespace.trailing" and "hooks.whitespace.tabinindent".
+# Those variables should contain valid Perl regular expressions. The names of modified
+# files will be matched against those regexes.
+
+# git-diff-index needs a valid commit to compare to
+if git rev-parse --verify HEAD >/dev/null 2>&1
+then
+ against=HEAD
+else
+ # Initial commit: diff against an empty tree object
+ against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+
+# By default, we disallow trailing whitespace for the following files, but the check for C/C++ sources
+# happens in the tab-in-indent check to avoid confusing users with duplicate error messages
+TRAILING_WHITESPACE_DEFAULT='.*(Makefile.am|configure.ac|dune.module|README|README.SVN|COPYING|INSTALL|TODO|\.cmake|CMakeLists.txt|\.pc\.in)$'
+
+# By default, we disallow tabs in indents and trailing whitespace in C/C++ source files
+TAB_IN_INDENT_DEFAULT='\.(cpp|hpp|cc|hh|c|h)$'
+
+# Get user preferences
+TRAILING_WHITESPACE_FILES=$(git config hooks.whitespace.trailing)
+
+# Set default regex for disallowing trailing whitespace if the user did not set anything.
+# We need to check the return value of git-config to distinguish the case
+# when the user set an empty value
+if [ $? -ne 0 ];
+then
+ TRAILING_WHITESPACE_FILES="$TRAILING_WHITESPACE_DEFAULT"
+fi
+
+
+TAB_IN_INDENT_FILES=$(git config hooks.whitespace.tabinindent)
+
+# Set default regex for disallowing tabs if the user did not set anything.
+# We need to check the return value of git-config to distinguish the case
+# when the user set an empty value
+if [ $? -ne 0 ];
+then
+ TAB_IN_INDENT_FILES="$TAB_IN_INDENT_DEFAULT"
+fi
+
+
+# Unfortunately, we have to mess directly with the repository config file,
+# as git won't honor a custom config file specified by GIT_CONFIG
+
+# backup repository-local user setting for core.whitespace
+USER_WHITESPACE=$(git config --local --get core.whitespace)
+if [ $? -ne 0 ];
+then
+ USER_HAS_CUSTOM_WHITESPACE=0
+else
+ USER_HAS_CUSTOM_WHITESPACE=1
+fi
+
+# Figure out how to call xargs to make sure it won't invoke its argument with
+# an empty argument list. BSD xargs will not do that by default, while GNU xargs
+# needs -r to do the same. So we start by checking whether xargs does the right
+# thing without options. Now there could be other obscure versions of xargs out
+# there (on clusters etc.) that behave in yet another way, so we try with -r as
+# well. If that fails, we throw a big error message at the user.
+
+# In the following line, xargs should not call false, so the return value should be 0.
+echo "" | xargs false
+
+if [ $? -ne 0 ]; then
+ # Let's try with -r
+ echo "" | xargs -r false
+ if [ $? -ne 0 ]; then
+ # Houston, we have a problem
+ if [ -z "$DUNE_WHITESPACE_IGNORE_XARGS" ]; then
+ echo "You seem to be lacking a version of xargs that is compatible to either BSD or GNU!" 1>&2
+ echo "Please file a bug report at http://dune-project.org about this issue with your exact operating system type and version!" 1>&2
+ echo "You can still use this hook by setting the environment variable DUNE_WHITESPACE_IGNORE_XARGS to 1, but please be aware" 1>&2
+ echo "that the hook might create false positives." 1>&2
+ echo "==============================================================" 1>&2
+ echo "Aborting the commit..." 1>&2
+ exit 99
+ else
+ SILENTXARGS=xargs
+ fi
+ else
+ SILENTXARGS="xargs -r"
+ fi
+else
+ SILENTXARGS=xargs
+fi
+
+
+fail=0
+done=0
+
+do_cleanup()
+{
+
+ if [ $done -ne 1 ];
+ then
+ echo "Error while executing whitespace checking pre-commit hook!" 1>&2
+ echo "There might still be whitespace errors in your commit!" 1>&2
+ fi
+
+ if [ $USER_HAS_CUSTOM_WHITESPACE -eq 1 ];
+ then
+ git config --replace-all core.whitespace "$USER_WHITESPACE"
+ else
+ git config --unset core.whitespace
+ fi
+
+ # be nice and let the commit go through if something went wrong along the
+ # way and we did not record a failure
+ exit $fail
+}
+
+trap do_cleanup EXIT
+
+# set custom value
+git config --replace-all core.whitespace trailing-space
+
+if [ -z "$TRAILING_WHITESPACE_FILES" ];
+then
+ git diff-index --check --cached $against --
+ result=$?
+else
+ git diff-index --cached --name-only $against | perl -ne "print if /$TRAILING_WHITESPACE_FILES/" | $SILENTXARGS git diff-index --check --cached $against --
+ result=$?
+fi
+
+if [ $result -ne 0 ];
+then
+ fail=1
+fi
+
+git config --replace-all core.whitespace trailing-space,tab-in-indent
+
+if [ -z "$TAB_IN_INDENT_FILES" ];
+then
+ git diff-index --check --cached $against --
+ result=$?
+else
+ git diff-index --cached --name-only $against | perl -ne "print if /$TAB_IN_INDENT_FILES/" | $SILENTXARGS git diff-index --check --cached $against --
+ result=$?
+fi
+
+if [ $result -ne 0 ];
+then
+ fail=1
+fi
+
+done=1
+
+# trap will call the cleanup code
--- /dev/null
+#!/bin/bash
+
+set -e
+
+canonicalname(){
+ if test $# -ne 1; then
+ echo Usage: canonicalname path >&2
+ return 1
+ fi
+ name="$1"
+ while test -L "$name"; do
+ if ! test -e "$name"; then
+ echo $name: file not found >&2
+ return 1
+ fi
+ if newname="`readlink $name`"; then
+ name="$newname"
+ else
+ echo "$(dirname $name)/$(basename $name)"
+ fi
+ done
+ echo $name
+}
+
+canonicalpath(){
+ if test $# -ne 1; then
+ echo Usage: canonicalpath path >&2
+ return 1
+ fi
+ (cd $(dirname $(canonicalname $1)) && pwd)
+}
+
+findm4dir() {
+ BINDIR="$(canonicalpath $0)"
+ # source-build
+ M4DIR="$BINDIR/../m4"
+ if test -f "$M4DIR/mpi-config.m4"; then
+ echo "$M4DIR"
+ return
+ fi
+ # installed
+ M4DIR="$BINDIR/../share/dune/aclocal"
+ if test -f "$M4DIR/mpi-config.m4"; then
+ echo "$M4DIR"
+ return
+ fi
+ # downloaded
+ M4DIR="$BINDIR"
+ if test -f "$M4DIR/mpi-config.m4"; then
+ echo "$M4DIR"
+ return
+ fi
+ echo "ERROR: could not find mpi-config.m4! Incomplete installation?" >&2
+ exit 1
+}
+
+version=0.1
+verbose=0
+
+usage()
+{
+ cat <<EOF
+mpi-config is a tool to help you determine the compiler and linker flags that
+you need in order to build your code with MPI. It is very similar to pkg-config,
+but doesn't rely on help from your MPI installation. If/when MPI implementations
+start supporting pkg-config then mpi-config will become obsolete.
+
+Usage: mpi-config [OPTIONS] [LIBRARIES]
+Options:
+ [--mpicc[=COMPILER]]
+ [--disable-cxx]
+ [--verbose]
+ [--version]
+ [--mpiversion]
+ [--libs]
+ [--cflags]
+
+EOF
+ exit $1
+}
+
+if test $# -eq 0 ; then
+ usage 1 1>&2
+fi
+
+while test $# -gt 0 ; do
+ case "$1" in
+ -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ case $1 in
+ --mpicc=*)
+ MPICC=$optarg
+ ;;
+ --version)
+ echo $version
+ exit 0
+ ;;
+ --verbose)
+ verbose=1
+ ;;
+ --disable-cxx)
+ disablecxx=yes
+ ;;
+ --mpiversion)
+ tasks="$tasks print_mpiversion"
+ ;;
+ --cflags)
+ tasks="$tasks print_cflags"
+ ;;
+ --ldflags)
+ tasks="$tasks print_ldflags"
+ ;;
+ --libs)
+ tasks="$tasks print_libs"
+ ;;
+ *)
+ usage 1 1>&2
+ ;;
+ esac
+ shift
+done
+
+if test x$MPICC = x ; then
+ MPICC=mpicc
+fi
+
+#
+# LIB
+#
+# load mpi-config.m4
+#
+
+# find m4 file
+M4DIR=`findm4dir`
+
+eval "$(
+m4 -I$M4DIR <<EOF
+changequote([, ])
+define([AC_DEFUN],[define([\$1],[\$2])])
+define([AC_MSG_CHECKING],[
+ if test $verbose -gt 0; then
+ echo -n "checking \$@..."
+ fi
+])
+define([AC_MSG_RESULT],[
+ if test $verbose -gt 0; then
+ echo " \$@"
+ fi
+])
+define([AC_MSG_NOTICE],[
+ if test $verbose -gt 0; then
+ echo "\$@"
+ fi
+])
+define([AC_MSG_ERROR],[
+ if test $verbose -gt 0; then
+ echo "Error: \$@"
+ exit 1
+ fi
+])
+include([mpi-config.m4])
+MPI_CONFIG_HELPER
+EOF
+)"
+
+#
+# output methods
+#
+
+print_mpiversion() {
+ get_mpiparameters
+ echo $MPI_VERSION
+}
+
+print_cflags() {
+ get_mpiparameters
+ if test x$disablecxx = xyes; then
+ DUNEMPICPPFLAGS="$DUNEMPICPPFLAGS $MPI_NOCXXFLAGS"
+ fi
+ echo $DUNEMPICPPFLAGS
+}
+
+print_ldflags() {
+ get_mpiparameters
+ echo $DUNEMPILDFLAGS
+}
+
+print_libs() {
+ get_mpiparameters
+ echo $DUNEMPILIBS
+}
+
+for task in $tasks; do
+ eval $task
+done
--- /dev/null
+#!/bin/bash
+
+set -e
+
+###############################################
+###
+### read lib
+###
+
+canonicalname(){
+ if test $# -ne 1; then
+ echo Usage: canonicalname path >&2
+ return 1
+ fi
+ file="$1"
+ if test ! -e "$file"; then
+ echo $file: file not found >&2
+ return 1
+ fi
+ # if this is a symlink, then follow the symlink
+ if test -L "$file"; then
+ fdir="`dirname \"$file\"`"
+ flink="`readlink \"$file\"`"
+ if test -e "$flink"; then
+ # these are absolute links, or links in the CWD
+ canonicalname "$flink"
+ else
+ canonicalname "$fdir/$flink"
+ fi
+ else
+ # if this is a file, then remember the filename and
+ # canonicalize the directory name
+ if test -f "$file"; then
+ fdir="`dirname \"$file\"`"
+ fname="`basename \"$file\"`"
+ fdir="`canonicalname \"$fdir\"`"
+ echo "$fdir/$fname"
+ fi
+ # if this is a directory, then create an absolute
+ # directory name and we are done
+ if test -d "$file"; then
+ (cd "$file"; pwd)
+ fi
+ fi
+}
+
+canonicalpath(){
+ if test $# -ne 1; then
+ echo Usage: canonicalpath path >&2
+ return 1
+ fi
+ dirname $(canonicalname "$1")
+}
+
+checkdebug () {
+ while test $# -gt 0; do
+ if test x$1 = x--debug; then
+ echo yes
+ return
+ fi
+ shift
+ done
+ echo no
+}
+
+DEBUG=`checkdebug $@`
+if test "x$DEBUG" = "xyes"; then
+ set -x
+ set -v
+fi
+
+export COMMAND_DIR="`canonicalpath $0`"
+
+# Read the modules find part
+. "$COMMAND_DIR/dunemodules.inc"
+
+#
+# test version checks
+#
+
+test_version_check () {
+ if ! check_version "$1" "$2"; then
+ echo "ERROR: version does not match (found $1, required $2)" >&2
+ #exit 1
+ else
+ echo "OK: version does match (found $1, required $2)" >&2
+ fi
+}
+
+test_version_check "1.2.3" ">= 1.2.5 || < 1.2.4"
+test_version_check "1.2.4" ">= 1.2.5 || < 1.2.4"
+test_version_check "1.2.5" ">= 1.2.5 || < 1.2.4"
+test_version_check "1.2" ">= 1.2.5 || < 1.2.4"
+
+test_version_check "1.2.3" ">= 1.2.5 && < 1.2.4"
+test_version_check "1.2.4" "< 1.2.5 && >= 1.2.4"
+
+test_version_check "1.2.3" ">= 1.2"
+test_version_check "1.2.3" "= 2.4.1"
+test_version_check "1.2.3" "= 1.2.3"
+test_version_check "1.2.3" "> 1.2"
+test_version_check "1.2.3" "= 1.2"
+test_version_check "1.2.3" "< 1.2"
+
+check_pattern()
+{
+ PATTERN=$PARSE_SUGDEP_PATTERN
+}
+
+parse_version()
+{
+ local deps="$1"
+ local name=""
+ local dep=""
+ local xdeps=""
+ echo start: $deps
+ while test -n "$deps"; do
+ PATTERN=$PARSE_SUGDEP_PATTERN
+ name=`echo $deps | sed -e "s/$PATTERN/\1/"`
+ ver=`echo $deps | sed -e "s/$PATTERN/\2/" -e 's/[()]//g'`
+ xdeps=`echo $deps | sed -e "s/$PATTERN/\3/"`
+ if test "$deps" = "$xdeps"; then
+ echo Error parsing dependency string \"$1\"
+ exit 1
+ fi
+ deps=$xdeps
+ echo $name version $ver ... $deps
+ done
+ echo done
+}
+
+parse_version "dune-common (>= 1.2), dune-istl (<999)"
+parse_version "alf (12) bart()c"
+parse_version "a b () c"
--- /dev/null
+#!/bin/bash
+
+make compile_XFAIL
--- /dev/null
+Makefile.in
+Makefile
--- /dev/null
+SUBDIRS=modules pkg scripts
+
+include $(top_srcdir)/am/global-rules
--- /dev/null
+Makefile.in
+Makefile
--- /dev/null
+# add_dune_gmp_flags(target1 target2 ...)
+# Function that adds GMP flags to the specified targets
+#
+function(add_dune_gmp_flags _targets)
+ if(GMP_FOUND)
+ foreach(_target ${_targets})
+ target_link_libraries(${_target} ${GMP_LIBRARIES})
+ set_property(TARGET ${_target}
+ APPEND_STRING
+ PROPERTY COMPILE_FLAGS "-DENABLE_GMP=1 ")
+ foreach(_path ${GMP_INCLUDE_DIRS})
+ set_property(TARGET ${_target}
+ APPEND_STRING
+ PROPERTY COMPILE_FLAGS "-I${_path}")
+ endforeach(_path ${GMP_INCLUDE_DIRS})
+ endforeach(_target ${_targets})
+ endif(GMP_FOUND)
+endfunction(add_dune_gmp_flags)
--- /dev/null
+# Module providing convenience functions for using METIS
+#
+# Provides the following functions:
+#
+# add_dune_metis_flags(target1 target2 ...)
+#
+# Adds the necessary flags to compile and link the targets with ParMETIS support.
+#
+function(add_dune_metis_flags _targets)
+ if(METIS_FOUND)
+ foreach(_target ${_targets})
+ target_link_libraries(${_target} ${METIS_LIBRARY})
+ endforeach(_target ${_targets})
+ set_property(TARGET ${_targets} APPEND PROPERTY
+ INCLUDE_DIRECTORIES "${METIS_INCLUDE_DIRS}")
+ endif(METIS_FOUND)
+endfunction(add_dune_metis_flags _targets)
--- /dev/null
+# Module providing convenience functions for using ParMETIS
+#
+# Provides the following functions:
+#
+# add_dune_parmetis_flags(target1 target2 ...)
+#
+# Adds the necessary flags to compile and link the targets with ParMETIS support.
+#
+function(add_dune_parmetis_flags _targets)
+ if(PARMETIS_FOUND)
+ foreach(_target ${_targets})
+ target_link_libraries(${_target} ${PARMETIS_LIBRARY} ${METIS_LIBRARY})
+ GET_TARGET_PROPERTY(_props ${_target} INCLUDE_DIRECTORIES)
+ string(REPLACE "_props-NOTFOUND" "" _props "${_props}")
+ SET_TARGET_PROPERTIES(${_target} PROPERTIES INCLUDE_DIRECTORIES
+ "${_props};${PARMETIS_INCLUDE_DIRS}")
+ GET_TARGET_PROPERTY(_props ${_target} COMPILE_DEFINITIONS)
+ string(REPLACE "_props-NOTFOUND" "" _props "${_props}")
+ SET_TARGET_PROPERTIES(${_target} PROPERTIES COMPILE_DEFINITIONS
+ "${_props};ENABLE_PARMETIS")
+ endforeach(_target ${_targets})
+ add_dune_mpi_flags(${_targets})
+ endif(PARMETIS_FOUND)
+endfunction(add_dune_parmetis_flags)
--- /dev/null
+# module providing convenience mehtods for compiling bianries with UMFPack support
+#
+# Provides the following functions:
+#
+# add_dune_umfpack_flags(target1 target2...)
+#
+# adds UMFPack flags to the targets for compilation and linking
+function(add_dune_umfpack_flags _targets)
+ if(UMFPACK_FOUND)
+ foreach(_target ${_targets})
+ target_link_libraries(${_target} ${UMFPACK_DUNE_LIBRARIES})
+ get_target_property(_props ${_target} COMPILE_FLAGS)
+ string(REPLACE "_props-NOTFOUND" "" _props "${_props}")
+ set_target_properties(${_target} PROPERTIES COMPILE_FLAGS
+ "${_props} ${UMFPACK_DUNE_COMPILE_FLAGS} -DENABLE_UMFPACK")
+ endforeach(_target ${_targets})
+ endif(UMFPACK_FOUND)
+endfunction(add_dune_umfpack_flags)
\ No newline at end of file
--- /dev/null
+set(modules
+ AddGMPFlags.cmake
+ AddMETISFlags.cmake
+ AddParMETISFlags.cmake
+ AddUMFPackFlags.cmake
+ CheckCXX11Features.cmake
+ CheckSharedPtr.cmake
+ DuneBoost.cmake
+ DuneCMakePackageConfigHelpers.cmake
+ DuneCommonMacros.cmake
+ DuneCxaDemangle.cmake
+ DuneDoc.cmake
+ DuneDoxygen.cmake
+ DuneMacros.cmake
+ DuneMPI.cmake
+ DunePkgConfig.cmake
+ DuneStreams.cmake
+ DuneTestMacros.cmake
+ DuneTests.cmake
+ FindBoostFusion.cmake
+ FindGMP.cmake
+ FindInkscape.cmake
+ FindMETIS.cmake
+ FindMProtect.cmake
+ FindParMETIS.cmake
+ FindUMFPack.cmake
+ Headercheck.cmake
+ LanguageSupport.cmake
+ UseInkscape.cmake
+ UseLATEX.cmake)
+install(FILES ${modules} DESTINATION ${DUNE_INSTALL_MODULEDIR})
--- /dev/null
+#
+# Module that checks for supported C++11 (former C++0x) features.
+#
+# Sets the follwing variable:
+#
+# HAVE_NULLPTR True if nullptr is available
+# HAVE_ARRAY True if header <array> and fill() are available
+# HAVE_ATTRIBUTE_ALWAYS_INLINE True if attribute always inline is supported
+# HAS_ATTRIBUTE_UNUSED True if attribute unused is supported
+# HAS_ATTRIBUTE_DEPRECATED True if attribute deprecated is supported
+# HAS_ATTRIBUTE_DEPRECATED_MSG True if attribute deprecated("msg") is supported
+# HAVE_INTEGRAL_CONSTANT True if compiler supports integral_constant
+# HAVE_STATIC_ASSERT True if static_assert is available
+# HAVE_VARIADIC_TEMPLATES True if variadic templates are supprt
+# HAVE_VARIADIC_CONSTRUCTOR_SFINAE True if variadic constructor sfinae is supported
+# HAVE_RVALUE_REFERENCES True if rvalue references are supported
+# HAVE_STD_CONDITIONAL True if std::conditional is supported
+# HAVE_INITIALIZER_LIST True if initializer list is supported
+
+include(CMakePushCheckState)
+cmake_push_check_state()
+
+# test for C++11 flags
+include(TestCXXAcceptsFlag)
+
+if(NOT DISABLE_GXX0XCHECK)
+ # try to use compiler flag -std=c++11
+ check_cxx_accepts_flag("-std=c++11" CXX_FLAG_CXX11)
+endif(NOT DISABLE_GXX0XCHECK)
+
+if(CXX_FLAG_CXX11)
+ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++11")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11 ")
+ set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -std=c++11 ")
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11 ")
+ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -std=c++11 ")
+ set(CXX_STD11_FLAGS "-std=c++11")
+else()
+ if(NOT DISABLE_GXX0XCHECK)
+ # try to use compiler flag -std=c++0x for older compilers
+ check_cxx_accepts_flag("-std=c++0x" CXX_FLAG_CXX0X)
+ endif(NOT DISABLE_GXX0XCHECK)
+ if(CXX_FLAG_CXX0X)
+ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++0x" )
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x ")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++0x ")
+ set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -std=c++0x ")
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++0x ")
+ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -std=c++0x ")
+ set(CXX_STD11_FLAGS "-std=c++0x")
+ endif(CXX_FLAG_CXX0X)
+endif(CXX_FLAG_CXX11)
+# perform tests
+include(CheckCXXSourceCompiles)
+
+# nullptr
+check_cxx_source_compiles("
+ int main(void)
+ {
+ char* ch = nullptr;
+ return 0;
+ }
+" HAVE_NULLPTR
+)
+include(CheckIncludeFile)
+include(CheckIncludeFileCXX)
+
+if(NOT DISABLE_TR1_HEADERS)
+# array and fill
+check_cxx_source_compiles("
+ #include <array>
+
+ int main(void)
+ {
+ std::array<int,2> a;
+ a.fill(9);
+ return 0;
+ }
+" HAVE_ARRAY
+)
+
+# Search for some tr1 headers
+foreach(_HEADER tuple tr1/tuple type_traits tr1/type_traits)
+ string(REPLACE "/" "_" _HEADER_VAR ${_HEADER})
+ string(TOUPPER ${_HEADER_VAR} _HEADER_VAR )
+ check_include_file_cxx(${_HEADER} "HAVE_${_HEADER_VAR}")
+endforeach(_HEADER tuple tr1/tuple tr1/type_traits)
+
+# Check for hash support
+check_include_file_cxx("functional" "HAVE_FUNCTIONAL")
+if(NOT HAVE_FUNCTIONAL)
+ check_include_file_cxx("tr1/functional" "HAVE_TR1_FUNCTIONAL")
+ if(HAVE_TR1_FUNCTIONAL)
+ set(_functional_header "tr1/functional")
+ set(_hash_type "std::tr1::hash")
+ set(_hash_variable "HAVE_TR1_HASH")
+ endif(HAVE_TR1_FUNCTIONAL)
+else()
+ set(_functional_header "functional")
+ set(_hash_type "std::hash")
+ set(_hash_variable "HAVE_STD_HASH")
+endif(NOT HAVE_FUNCTIONAL)
+
+if(_functional_header)
+ check_cxx_source_compiles("
+ #include <${_functional_header}>
+ int main(void){
+ ${_hash_type}<int> hasher; hasher(42);
+ }
+" ${_hash_variable})
+endif(_functional_header)
+
+# Check whether if std::integral_constant< T, v > is supported and casts into T
+check_cxx_source_compiles("
+ #include <type_traits>
+ void f( int ){}
+
+ int main(void){
+ f( std::integral_constant< int, 42 >() );
+ }
+" HAVE_INTEGRAL_CONSTANT
+)
+
+endif(NOT DISABLE_TR1_HEADERS)
+
+# __attribute__((unused))
+check_cxx_source_compiles("
+ int main(void)
+ {
+ int __attribute__((unused)) foo;
+ return 0;
+ };
+" HAS_ATTRIBUTE_UNUSED
+)
+
+# __attribute__((deprecated))
+check_cxx_source_compiles("
+#define DEP __attribute__((deprecated))
+ class bar
+ {
+ bar() DEP;
+ };
+
+ class peng { } DEP;
+
+ template <class T>
+ class t_bar
+ {
+ t_bar() DEP;
+ };
+
+ template <class T>
+ class t_peng {
+ t_peng() {};
+ } DEP;
+
+ void foo() DEP;
+
+ void foo() {};
+
+ int main(void)
+ {
+ return 0;
+ };
+" HAS_ATTRIBUTE_DEPRECATED
+)
+
+# __attribute__((deprecated("msg")))
+check_cxx_source_compiles("
+#define DEP __attribute__((deprecated(\"message\")))
+ class bar {
+ bar() DEP;
+ };
+
+ class peng { } DEP;
+
+ template <class T>
+ class t_bar
+ {
+ t_bar() DEP;
+ };
+
+ template <class T>
+ class t_peng
+ {
+ t_peng() {};
+ } DEP;
+
+ void foo() DEP;
+
+ void foo() {};
+
+ int main(void)
+ {
+ return 0;
+ };
+" HAS_ATTRIBUTE_DEPRECATED_MSG
+)
+
+# static assert
+check_cxx_source_compiles("
+ int main(void)
+ {
+ static_assert(true,\"MSG\");
+ return 0;
+ }
+" HAVE_STATIC_ASSERT
+)
+
+# variadic template support
+check_cxx_source_compiles("
+ #include <cassert>
+
+ template<typename... T>
+ int addints(T... x);
+
+ int add_ints()
+ {
+ return 0;
+ }
+
+ template<typename T1, typename... T>
+ int add_ints(T1 t1, T... t)
+ {
+ return t1 + add_ints(t...);
+ }
+
+ int main(void)
+ {
+ assert( 5 == add_ints(9,3,-5,-2) );
+ return 0;
+ }
+" HAVE_VARIADIC_TEMPLATES
+)
+
+# SFINAE on variadic template constructors within template classes
+check_cxx_source_compiles("
+ #include <functional>
+
+ template<typename... U>
+ struct A
+ {
+ template<typename... T,
+ typename = typename std::enable_if<(sizeof...(T) < 2)>::type
+ >
+ A(T... t)
+ : i(1)
+ {}
+
+ template<typename... T,
+ typename = typename std::enable_if<(sizeof...(T) >= 2)>::type,
+ typename = void
+ >
+ A(T... t)
+ : i(-1)
+ {}
+
+ A()
+ : i(1)
+ {}
+
+ int i;
+ };
+
+ int main(void)
+ {
+ return (A<int>().i + A<int>(2).i + A<int>(\"foo\",3.4).i + A<int>(8,'a',A<int>()).i == 0 ? 0 : 1);
+ }
+" HAVE_VARIADIC_CONSTRUCTOR_SFINAE
+)
+
+# rvalue references
+check_cxx_source_compiles("
+ #include <cassert>
+ #include <utility>
+ int foo(int&& x) { return 1; }
+ int foo(const int& x) { return -1; }
+
+ template<typename T>
+ int forward(T&& x)
+ {
+ return foo(std::forward<T>(x));
+ }
+
+ int main(void)
+ {
+ int i = 0;
+ assert( forward(i) + forward(int(2)) == 0);
+ return 0;
+ }
+" HAVE_RVALUE_REFERENCES
+)
+
+# std::conditional
+check_cxx_source_compiles("
+ #include <type_traits>
+
+ int main(void){
+ return std::conditional<true,std::integral_constant<int,0>,void>::type::value;
+ }
+" HAVE_STD_CONDITIONAL
+)
+
+# initializer list
+check_cxx_source_compiles("
+ #include <initializer_list>
+ #include <vector>
+
+ struct A
+ {
+ A(std::initializer_list<int> il)
+ : vec(il)
+ {}
+
+ std::vector<int> vec;
+ };
+
+ int main(void)
+ {
+ A a{1,3,4,5};
+ return 0;
+ }
+" HAVE_INITIALIZER_LIST
+)
+
+cmake_pop_check_state()
--- /dev/null
+# Module checks for shared_ptr support.
+#
+# Sets the following variables:
+#
+# HAVE_BOOST_MAKE_SHARED_HPP: True if boost/make_shared.hpp is found
+# SHARED_PTR_NAMESPACE: Namespace of shared_ptr (e.g. std)
+# SHARED_PTR_HEADER: The name of header file supplying shared_ptr
+#
+# check if make_shared works
+macro(check_make_shared)
+ include(CheckIncludeFileCXX)
+
+ if(SHARED_PTR_NAMESPACE EQUAL "boost")
+ check_include_file_cxx("boost/make_shared.hpp" HAVE_BOOST_MAKE_SHARED_HPP)
+ endif(SHARED_PTR_NAMESPACE EQUAL "boost")
+
+ check_include_file_cxx("boost/shared_ptr.hpp" HAVE_BOOST_SHARED_PTR_HPP)
+
+ check_cxx_source_compiles("
+ #if defined(HAVE_MEMORY)
+ # include <memory>
+ #endif
+ #if defined(HAVE_TR1_MEMORY)
+ # include <tr1/memory>
+ #endif
+ #if defined(HAVE_BOOST_SHARED_PTR_HPP) && defined(HAVE_BOOST_MAKE_SHARED_HPP)
+ # include <boost/shared_ptr.hpp>
+ # include <boost/make_shared.hpp>
+ #endif
+
+ int main(void)
+ {
+ ${SHARED_PTR_NAMESPACE}::make_shared<int>(3);
+ return 0;
+ }
+ " HAVE_MAKE_SHARED)
+endmacro(check_make_shared)
+
+# check location of shared_ptr header file and the necessary namespace
+include(CheckCXXSourceCompiles)
+
+# search namespace
+foreach(SHARED_PTR_NAMESPACE_ "std" "tr1" "std::tr1" "boost")
+ check_cxx_source_compiles("
+ #include <memory>
+ #include <string>
+
+ using ${SHARED_PTR_NAMESPACE_}::shared_ptr;
+ using namespace std;
+
+ int main(void)
+ {
+ shared_ptr<string> test_ptr(new string(\"test string\"));
+ return 0;
+ }"
+ SHARED_PTR_NAMESPACE_FOUND)
+
+ if(SHARED_PTR_NAMESPACE_FOUND)
+ #search header name
+ foreach(SHARED_PTR_HEADER_ "<memory>" "<tr1/memory>" "<boost/shared_ptr.hpp>")
+ check_cxx_source_compiles("
+ # include ${SHARED_PTR_HEADER_}
+ #include <string>
+
+ using ${SHARED_PTR_NAMESPACE_}::shared_ptr;
+ using namespace std;
+
+ int main(void)
+ {
+ shared_ptr<string> test_ptr(new string(\"test string\"));
+ return 0;
+ }"
+ SHARED_PTR_HEADER_FOUND)
+
+ if(SHARED_PTR_HEADER_FOUND)
+ # save result
+ set(SHARED_PTR_NAMESPACE ${SHARED_PTR_NAMESPACE_})
+ set(SHARED_PTR_HEADER ${SHARED_PTR_HEADER_})
+ check_make_shared()
+ return()
+ endif(SHARED_PTR_HEADER_FOUND)
+ endforeach(SHARED_PTR_HEADER_)
+ endif(SHARED_PTR_NAMESPACE_FOUND)
+endforeach(SHARED_PTR_NAMESPACE_)
--- /dev/null
+# Searches for boost and provides the following function:
+#
+# add_dune_boost_flags(targets [LINK_ALL_BOOST_LIBRARIES]
+# LIBRARIES lib1 lib2 ...)
+#
+# Adds boost compiler flags and libraries, and activates
+# Boost for the specified targets. Libraries can either be
+# provided by listing them after the LIBRARIES keyword or one
+# can request linking with all available boost libraries by
+# passing the LINK_ALL_BOOST_LIBRARIES option to the function
+# call.
+find_package(Boost)
+set(HAVE_DUNE_BOOST ${Boost_FOUND})
+
+#add all boost realted flags to ALL_PKG_FLAGS, this must happen regardless of a target using add_dune_boost_flags
+if(HAVE_DUNE_BOOST)
+ set_property(GLOBAL APPEND PROPERTY ALL_PKG_FLAGS "-DENABLE_BOOST=1")
+ foreach(dir ${Boost_INCLUDE_DIRS})
+ set_property(GLOBAL APPEND PROPERTY ALL_PKG_FLAGS "-I${dir}")
+ endforeach()
+endif()
+
+function(add_dune_boost_flags _targets)
+ cmake_parse_arguments(DUNE_BOOST LINK_ALL_BOOST_LIBRARIES "" LIBRARIES ${ARGN})
+ if(Boost_FOUND)
+ include_directories("${Boost_INCLUDE_DIRS}")
+ foreach(_target ${_targets})
+ if(DUNE_BOOST_LINK_ALL_BOOST_LIBRARIES)
+ target_link_libraries(${_target} "${DUNE_Boost_LIBRARIES}")
+ else(DUNE_BOOST_LINK_ALL_BOOST_LIBRARIES)
+ target_link_libraries(${_target} "${DUNE_BOOST_LIBRARIES}")
+ endif(DUNE_BOOST_LINK_ALL_BOOST_LIBRARIES)
+ # The definitions are a hack as we do not seem to know which MPI implementation was
+ # found.
+ GET_TARGET_PROPERTY(_props ${_target} COMPILE_FLAGS)
+ string(REPLACE "_props-NOTFOUND" "" _props "${_props}")
+ SET_TARGET_PROPERTIES(${_target} PROPERTIES COMPILE_FLAGS
+ "${_props} -DENABLE_BOOST=1")
+ endforeach(_target)
+ endif(Boost_FOUND)
+endfunction(add_dune_boost_flags)
\ No newline at end of file
--- /dev/null
+#
+# A poor mans version of CMakePackageConfigHelpers.cmake for as a substitute
+# for old Cmake versions.
+#
+# Provides the function
+# configure_package_config_file infile outfile INSTALL_DESTINATION relative_install_path
+# [PATH_VARS relative_path_varname1 ...])
+#
+# all paths are assumed to be relative!
+#
+find_file(CMakePkgConfigHelpersMacroFile CMakePackageConfigHelpers.cmake PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH})
+
+if(CMakePkgConfigHelpersMacroFile)
+ include(CMakePackageConfigHelpers)
+else(CMakePkgConfigHelpersMacroFile)
+ function(configure_package_config_file infile outfile)
+ include(CMakeParseArguments)
+ cmake_parse_arguments(PMPKG "" "INSTALL_DESTINATION" "PATH_VARS" "${ARGN}")
+ if(NOT PMPKG_INSTALL_DESTINATION)
+ message(FATAL_ERROR "configure_package_config_file needs an option INSTALL_DESTINATION with a relative path")
+ endif(NOT PMPKG_INSTALL_DESTINATION)
+ # asume that PMPKG_INSTALL_DESTINATION is relative
+ string(REGEX REPLACE "[^/]+" ".." prefix_path ${PMPKG_INSTALL_DESTINATION})
+ set(PACKAGE_INIT "# Set prefix to source dir
+get_filename_component(PACKAGE_PREFIX_DIR \"\${CMAKE_CURRENT_LIST_DIR}/${prefix_path}\" ABSOLUTE)
+macro(set_and_check _var _file)
+ set(\${_var} \"\${_file}\")
+ if(NOT EXISTS \"\${_file}\")
+ message(FATAL_ERROR \"File or directory \${_file} referenced by variable \${_var} does not exist !\")
+ endif()
+endmacro()")
+ if(PMPKG_PATH_VARS)
+ foreach(varname ${PMPKG_PATH_VARS})
+ set(PACKAGE_${varname} "\${PACKAGE_PREFIX_DIR}/${${varname}}")
+ endforeach(varname "${PMPKG_PATH_VARS}")
+ endif(PMPKG_PATH_VARS)
+ configure_file(${infile} ${outfile} @ONLY)
+ endfunction(configure_package_config_file infile outfile)
+endif(CMakePkgConfigHelpersMacroFile)
--- /dev/null
+# This cmake file holds tests and directives that are executed
+# for the module dune-common and have to be executed by
+# all dependent modules
+#
+# Specifically it configure the DUNE debug streams and
+# tests whether std::shared_ptr, LAPACK and BLAS are available.
+#
+include(DuneStreams)
+dune_set_minimal_debug_level()
+
+include(CheckSharedPtr)
+if(Fortran_Works)
+ # search for lapack
+ find_package(LAPACK)
+ set(HAVE_LAPACK ${LAPACK_FOUND})
+ set(HAVE_BLAS ${BLAS_FOUND})
+else(Fortran_Works)
+ set(HAVE_LAPACK Off)
+ set(HAVE_BLAS Off)
+ # Write an empty FC header
+ file(WRITE ${CMAKE_BINARY_DIR}/FC.h "")
+endif(Fortran_Works)
+
+find_package(GMP)
+include(AddGMPFlags)
+find_package(Inkscape)
+include(UseInkscape)
+include(FindMProtect)
+include(DuneBoost)
--- /dev/null
+# Module that checks whether the compiler supports the
+# abi::__cxa_demangle function required to
+# make the type names returned by typeid() human-readable
+#
+# Sets the following variable:
+# HAVE_CXA_DEMANGLE
+#
+# perform tests
+include(CheckCXXSourceCompiles)
+
+CHECK_CXX_SOURCE_COMPILES("#include <cxxabi.h>
+int main(void){
+ int foobar = 0;
+ const char *foo = typeid(foobar).name();
+ int status;
+ char *demangled = abi::__cxa_demangle( foo, 0, 0, &status );
+}" HAVE_CXA_DEMANGLE)
--- /dev/null
+#
+# Module that provides a custom target make doc at the top level
+# directory and utility macros for creating install directives
+# that make sure that the files to be installed are previously
+# generated even if make doc was not called.
+#
+# All documentation (Latex, Doxygen) will be generated during
+# make doc.
+# It provides the following macros:
+#
+# create_doc_install(FILENAME TARGETDIR [DEPENDENCY])
+#
+# creates a target for installing the file FILENAME
+# to the directory TARGETDIR.
+# If DEPENDENCY is specified, this is a dependency for
+# the installation. Otherwise FILENAME becomes the dependency
+#
+# dune_add_latex_document()
+
+FIND_PACKAGE(LATEX)
+FIND_PROGRAM(IMAGEMAGICK_CONVERT convert
+ DOC "The convert program that comes with ImageMagick (available at http://www.imagemagick.org)."
+ )
+set(LATEX_USABLE "ON")
+
+if(NOT LATEX_COMPILER)
+ message(WARNING " Need latex to create documentation!")
+ set(LATEX_USABLE)
+endif(NOT LATEX_COMPILER)
+if(NOT BIBTEX_COMPILER)
+ message(WARNING " Need bibtex to create documentation!")
+ set(LATEX_USABLE)
+endif(NOT BIBTEX_COMPILER)
+if(NOT MAKEINDEX_COMPILER)
+ message(WARNING " Need makeindex to create documentation!")
+ set(LATEX_USABLE)
+endif(NOT MAKEINDEX_COMPILER)
+if(NOT IMAGEMAGICK_CONVERT)
+ message(WARNING " Need imagemagick to create latex documentation!")
+ set(LATEX_USABLE)
+endif(NOT IMAGEMAGICK_CONVERT)
+if(LATEX_USABLE)
+ set(LATEX_MANGLE_TARGET_NAMES "ON" CACHE INTERNAL "Mangle target names to allow multiple latex documents")
+ include(UseLATEX)
+endif(LATEX_USABLE)
+
+
+add_custom_target(doc)
+
+
+MACRO(create_doc_install filename targetdir)
+ dune_common_script_dir(SCRIPT_DIR)
+ get_filename_component(targetfile ${filename} NAME)
+ # The doc file might be in CMAKE_CURRENT_<SOURCE|BINARY>_DIR
+ # Depending on whether this is a tarball or not
+ set(_src_file _src_file-NOTFOUND)
+ find_file(_src_file ${targetfile} ${CMAKE_CURRENT_SOURCE_DIR})
+ if(NOT _src_file)
+ set(_src_file ${filename})
+ set(_need_to_generate TRUE)
+ endif(NOT _src_file)
+ set(install_command ${CMAKE_COMMAND} -D FILES=${_src_file} -D DIR=${CMAKE_INSTALL_PREFIX}/${targetdir} -P ${SCRIPT_DIR}/InstallFile.cmake)
+ # create a custom target for the installation
+ if("${ARGC}" EQUAL "3" AND _need_to_generate)
+ set(_depends ${ARGV2})
+ else("${ARGC}" EQUAL "3" AND _need_to_generate)
+ set(_depends ${_src_file})
+ endif("${ARGC}" EQUAL "3" AND _need_to_generate)
+ add_custom_target(install_${targetfile} ${install_command}
+ COMMENT "Installing ${filename} to ${targetdir}"
+ DEPENDS ${_depends})
+ # When installing, call cmake install with the above install target and add the file to install_manifest.txt
+ install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" --build \"${CMAKE_BINARY_DIR}\" --target install_${targetfile} )
+ LIST(APPEND CMAKE_INSTALL_MANIFEST_FILES ${CMAKE_INSTALL_PREFIX}/${targetdir}/${targetfile})")
+ENDMACRO(create_doc_install)
+
+
+MACRO(dune_add_latex_document tex_file)
+ # We assume that we always generate a PDF file.
+ # If the corresponding pdf file already exists in the source tree
+ # we do not add a rule to build it.
+ string(REGEX REPLACE "(.+).tex" "\\1.pdf" file ${tex_file})
+ string(REGEX REPLACE "/" "_" "${CMAKE_CURRENT_SOURCE_DIR}/${file}" filevar ${file})
+ set(filevar "filevar-NOTFOUND")
+ find_file(filevar ${tex_file} ${CMAKE_CURRENT_SOURCE_DIR})
+ if(filevar)
+ if(LATEX_USABLE)
+ # add rule to create latex document
+ add_latex_document(${tex_file} ${ARGN} MANGLE_TARGET_NAMES)
+ else(LATEX_USABLE)
+ message(WARNING "Not adding rule to create ${file} as LaTEX is not usable!")
+ endif(LATEX_USABLE)
+ else(filevar)
+ # Check for the pdf file
+ set(pdffilevar "pdffilevar-NOTFOUND")
+ find_file(pdffilevar ${file} ${CMAKE_CURRENT_SOURCE_DIR})
+ if(NOT pdffilevar)
+ message(SEND_ERROR "No tex source ${tex_file} and no generated ${file} found!")
+ endif(NOT pdffilevar)
+ endif(filevar)
+ENDMACRO(dune_add_latex_document tex_file)
+
+# Support building documentation with doxygen.
+include(DuneDoxygen)
--- /dev/null
+# Module for building documentation using doxygen.
+#
+# provides the following macros:
+#
+# add_doxgen_target
+#
+# This macro creates a target for building (doxygen_${ProjectName}) and installing
+# (doxygen_install_${ProjectName}) the generated doxygen documentation.
+# The documentation is built during the top-level make doc call. We have added a dependency
+# that makes sure it is built before running make install.
+#
+#
+FIND_PACKAGE(Doxygen)
+
+#
+# Set DOT_TRUE for the Doxyfile generation.
+#
+if (NOT DOXYGEN_DOT_FOUND)
+ set(DOT_TRUE '\#')
+endif (NOT DOXYGEN_DOT_FOUND)
+
+add_custom_target(doxygen_install)
+
+#
+# prepare_doxyfile()
+# This functions adds the necessary routines for the generation of the
+# Doxyfile[.in] files needed to doxygen.
+MACRO (prepare_doxyfile)
+ message(STATUS "using ${DOXYSTYLE_FILE} to create doxystyle file")
+ set(make_doxyfile_command ${CMAKE_COMMAND} -D DOT_TRUE=${DOT_TRUE} -D DUNEWEB_TRUE=\# -D ProjectName=${ProjectName} -D DUNE_MOD_VERSION=${DUNE_MOD_VERSION} -D DOXYSTYLE=${DOXYSTYLE_FILE} -D DOXYLOCAL=${CMAKE_CURRENT_SOURCE_DIR}/Doxylocal -D abs_top_srcdir=${CMAKE_SOURCE_DIR} -D srcdir=${CMAKE_CURRENT_SOURCE_DIR} -D top_srcdir=${CMAKE_SOURCE_DIR} -P ${SCRIPT_DIR}/CreateDoxyFile.cmake)
+ add_custom_command (OUTPUT Doxyfile.in Doxyfile
+ COMMAND ${make_doxyfile_command} COMMENT "Creating Doxyfile.in")
+ add_custom_target(Doxyfile DEPENDS Doxyfile.in Doxyfile)
+ENDMACRO (prepare_doxyfile)
+
+#
+# add_doxgen_target
+#
+# This macro creates a target for building (doxygen_${ProjectName}) and installing
+# (doxygen_install_${ProjectName}) the generated doxygen documentation.
+# The documentation is built during the top-level make doc call. We have added a dependency
+# that make sure it is built before running make install.
+MACRO (add_doxygen_target)
+ dune_common_script_dir(SCRIPT_DIR)
+ if("${CMAKE_PROJECT_NAME}" STREQUAL "dune-common")
+ set(DOXYSTYLE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/Doxystyle)
+ endif("${CMAKE_PROJECT_NAME}" STREQUAL "dune-common")
+ message(STATUS "Using scripts from ${SCRIPT_DIR} for creating doxygen stuff.")
+ set(_src_file _src_file-NOTFOUND)
+ find_file(_src_file index.html ${CMAKE_CURRENT_SOURCE_DIR}/html)
+ if(_src_file)
+ set(_src_dir ${CMAKE_CURRENT_SOURCE_DIR})
+ add_custom_target(doxygen_${ProjectName})
+ else(_src_file)
+ if(DOXYGEN_FOUND)
+ prepare_doxyfile()
+ # A custom command that exectutes doxygen
+ add_custom_command(OUTPUT html COMMAND
+ ${CMAKE_COMMAND} -D DOXYGEN_EXECUTABLE=${DOXYGEN_EXECUTABLE} -P ${SCRIPT_DIR}/RunDoxygen.cmake
+ COMMENT "Running doxygen documentation. This may take a while"
+ DEPENDS Doxyfile)
+ # Create a target for building the doxygen documentation of a module,
+ # that is run during make doc.
+ add_custom_target(doxygen_${ProjectName} DEPENDS html)
+ add_dependencies(doc doxygen_${ProjectName})
+ endif(DOXYGEN_FOUND)
+ set(_src_dir ${CMAKE_CURRENT_BINARY_DIR})
+ endif(_src_file)
+
+ # Use a cmake call to install the doxygen documentation and create a
+ # target for it
+ include(GNUInstallDirs)
+ # When installing call cmake install with the above install target
+ install(CODE
+ "execute_process(COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target doxygen_${ProjectName}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+ file(GLOB doxygenfiles
+ GLOB ${_src_dir}/html/*.html
+ ${_src_dir}/html/*.png
+ ${_src_dir}/html/*.css
+ ${_src_dir}/html/*.gif)
+ set(doxygenfiles \"\${doxygenfiles}\")
+ foreach(_file \${doxygenfiles})
+ get_filename_component(_basename \${_file} NAME)
+ LIST(APPEND CMAKE_INSTALL_MANIFEST_FILES ${CMAKE_INSTALL_FULL_DOCDIR}/doxygen/\${_basename})
+ endforeach(_file in \${doxygenfiles})
+ file(INSTALL \${doxygenfiles} DESTINATION ${CMAKE_INSTALL_FULL_DOCDIR}/doxygen)
+ message(STATUS \"Installed doxygen into ${CMAKE_INSTALL_FULL_DOCDIR}/doxygen\")")
+
+ENDMACRO (add_doxygen_target)
--- /dev/null
+# Searches for MPI and thread support and sets the following
+# DUNE specific flags:
+#
+# MPI_DUNE_COMPILE_FLAGS Compiler flags for MPI applications.
+# MPI_DUNE_INCLUDE_PATH Include path for MPI applications.
+# MPI_DUNE_LINK_FLAGS Linker flags for MPI applications.
+# MPI_DUNE_LIBRARIES Libraries for MPI applications.
+#
+# The DUNE way to compile MPI applications is to use the CXX
+# compiler with MPI flags usually used for C. CXX bindings
+# are deactivated to prevent ABI problems.
+#
+# The following function is defined:
+#
+# add_dune_mpi_flags(targets)
+#
+# Adds the above flags and libraries to the specified targets.
+#
+
+find_package(MPI)
+find_package(Threads)
+
+if(MPI_CXX_FOUND)
+ set(HAVE_MPI ${MPI_CXX_FOUND})
+ # We do not support the CXX bindings of MPI
+ set(MPI_DUNE_COMPILE_FLAGS ${MPI_C_COMPILE_FLAGS} CACHE STRING
+ "Compile flags used by DUNE when compiling MPI programs")
+ set(MPI_DUNE_INCLUDE_PATH ${MPI_C_INCLUDE_PATH} CACHE STRING
+ "Include path used by DUNE when compiling MPI programs")
+ # There seems to be no target specific include path, use the global one.
+ include_directories(${MPI_DUNE_INCLUDE_PATH})
+ set(MPI_DUNE_LINK_FLAGS ${MPI_C_LINK_FLAGS} CACHE STRING
+ "Linker flags used by DUNE when compiling MPI programs")
+ set(MPI_DUNE_LIBRARIES ${CMAKE_THREAD_LIBS_INIT} ${MPI_C_LIBRARIES} CACHE STRING
+ "Libraries used by DUNE when linking MPI programs")
+
+ set_property(GLOBAL APPEND PROPERTY ALL_PKG_FLAGS "-DENABLE_MPI=1 -DMPICH_SKIP_MPICXX -DMPIPP_H")
+ foreach(dir ${MPI_DUNE_INCLUDE_PATH})
+ set_property(GLOBAL APPEND PROPERTY ALL_PKG_FLAGS "-I${dir}")
+ endforeach()
+
+ # Check whether the MPI-2 standard is supported
+ include(CMakePushCheckState)
+ include(CheckFunctionExists)
+ include(CheckCXXSourceCompiles)
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES};${MPI_DUNE_LIBRARIES})
+ set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} "-DENABLE_MPI=1 -DMPICH_SKIP_MPICXX -DMPIPP_H")
+ set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES};${MPI_DUNE_INCLUDE_PATH})
+ check_function_exists(MPI_Finalized MPI_2)
+
+ # proper version check
+ check_cxx_source_compiles("
+ #include <mpi.h>
+
+ #if !((MPI_VERSION > 2) || (MPI_VERSION == 2 && MPI_SUBVERSION >= 1))
+ fail with a horribe compilation error due to old MPI version
+ #endif
+
+ int main(int argc, char** argv)
+ {
+ MPI_Init(&argc,&argv);
+ MPI_Finalize();
+ }
+" MPI_VERSION_SUPPORTED)
+
+ cmake_pop_check_state()
+
+ # TODO: Turn into an error after 2.3 release
+ if(NOT MPI_VERSION_SUPPORTED)
+ MESSAGE(WARNING "Support for your MPI implementation is DEPRECATED and will be removed after the next release. Please upgrade to an MPI-2.1 compliant version.")
+ endif()
+endif(MPI_CXX_FOUND)
+
+# adds MPI flags to the targets
+function(add_dune_mpi_flags)
+ cmake_parse_arguments(ADD_MPI "SOURCE_ONLY;OBJECT" "" "" ${ARGN})
+ if(ADD_MPI_SOURCE_ONLY)
+ set(_prefix SOURCE)
+ else()
+ set(_prefix TARGET)
+ endif()
+ if(MPI_CXX_FOUND)
+ set_property(${_prefix} ${ADD_MPI_UNPARSED_ARGUMENTS} APPEND PROPERTY COMPILE_FLAGS ${MPI_DUNE_COMPILE_FLAGS})
+ set_property(${_prefix} ${ADD_MPI_UNPARSED_ARGUMENTS} APPEND PROPERTY COMPILE_DEFINITIONS ENABLE_MPI=1
+ MPICH_SKIP_MPICXX MPIPP_H)
+ if(NOT (ADD_MPI_SOURCE_ONLY OR ADD_MPI_OBJECT))
+ set_property(${_prefix} ${ADD_MPI_UNPARSED_ARGUMENTS} APPEND_STRING PROPERTY LINK_FLAGS ${MPI_DUNE_LINK_FLAGS})
+ foreach(target ${ADD_MPI_UNPARSED_ARGUMENTS})
+ target_link_libraries(${target} ${MPI_DUNE_LIBRARIES})
+ endforeach(target ${ADD_MPI_UNPARSED_ARGUMENTS})
+ endif(NOT (ADD_MPI_SOURCE_ONLY OR ADD_MPI_OBJECT))
+ endif(MPI_CXX_FOUND)
+endfunction(add_dune_mpi_flags)
--- /dev/null
+# Core DUNE module for CMake.
+#
+# Provides the following macros:
+#
+# dune_module_to_uppercase(upper_name module_name)
+#
+# Converts a module name given by module_name into an uppercase string
+# upper_name where all dashes (-) are replaced by underscores (_)
+# Example: dune-common -> DUNE_COMMON
+#
+# dune_module_information(MODULE_DIR [QUIET])
+#
+# Parse ${MODULE_DIR}/dune.module and provide that information.
+# If the second argument is QUIET no status message is printed.
+#
+#
+# dune_project()
+#
+# macro that should be called near the begin of the top level CMakeLists.txt.
+# Namely it sets up the module, defines basic variables and manages
+# depedencies.
+# Don't forget to call finalize_dune_project afterwards.
+#
+#
+# dune_create_dependency_tree()
+#
+# Creates the dependency tree of the module.
+#
+# dune_module_to_macro(_macro_name, _dune_module)
+#
+# Converts a module name given by _dune_module into a string _macro_name
+# where all dashes (-) are removed and letters after a dash are capitalized
+# Example: dune-grid-howto -> DuneGridHowto
+#
+# _macro_name: variable where the name will be stored.
+# _dune_module: the name of the dune module.
+#
+#
+# dune_regenerate_config_cmake()
+#
+# Creates a new config.h.cmake file in ${CMAKE_CURRENT_BINARY_DIR) that
+# consists of entries from ${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake
+# and includes non-private entries from the files config.h.cmake files
+# of all dependent modules.
+# Finally config.h is created from config.h.cmake.
+#
+#
+# dune_add_library(<basename> [NO_EXPORT] [ADD_LIBS <lib1> [<lib2> ...]]
+# [OBJECT] SOURCES <source1> [<source2> ...] [COMPILE_FLAGS <flags>])
+#
+# Creates shared and static libraries with the same basename.
+# <basename> is the basename of the library.
+# On Unix this creates lib<basename>.so and lib<BASENAME>.a.
+# Libraries that should be incorporate into this libary can
+# be specified with the ADD_LIBS option.
+# The libraries will be built in ${PROJECT_BINARY_DIR}/lib.
+# If the option NO_EXPORT is omitted the library is exported
+# for usage in other modules.
+#
+# Object libraries can now be created with dune_add_library(<target>
+# OBJECT <sources>). It will create a GLOBAL property
+# _DUNE_TARGET_OBJECTS:<target>_ that records the full path to the
+# source files. Theses can later be referenced by providing
+# _DUNE_TARGET_OBJECTS:<target>_ as one of the sources to dune_add_library
+#
+# finalize_dune_project()
+#
+# macro that should be called at the end of the top level CMakeLists.txt.
+# Namely it creates config.h and the cmake-config files,
+# some install directives and exports the module.
+#
+#
+# dune_target_link_libraries(BASENAME, LIBRARIES)
+#
+# Link libraries to the static and shared version of
+# library BASENAME
+#
+
+enable_language(C) # Enable C to skip CXX bindings for some tests.
+
+include(FeatureSummary)
+
+# Converts a module name given by _module into an uppercase string
+# _upper where all dashes (-) are replaced by underscores (_)
+# Example: dune-common -> DUNE_COMMON
+macro(dune_module_to_uppercase _upper _module)
+ string(TOUPPER "${_module}" ${_upper})
+ string(REPLACE "-" "_" ${_upper} "${${_upper}}")
+endmacro(dune_module_to_uppercase _upper _module)
+
+macro(find_dune_package module)
+ include(CMakeParseArguments)
+ cmake_parse_arguments(DUNE_FIND "REQUIRED" "VERSION" "" ${ARGN})
+ if(DUNE_FIND_REQUIRED)
+ set(required REQUIRED)
+ set_package_properties(${module} PROPERTIES TYPE REQUIRED)
+ else(DUNE_FIND_REQUIRED)
+ unset(required)
+ set_package_properties(${module} PROPERTIES TYPE RECOMMENDED)
+ endif(DUNE_FIND_REQUIRED)
+ if(DUNE_FIND_VERSION MATCHES "(>=|=|<=).*")
+ string(REGEX REPLACE "(>=|=|<=)(.*)" "\\1" DUNE_FIND_VERSION_OP ${DUNE_FIND_VERSION})
+ string(REGEX REPLACE "(>=|=|<=)(.*)" "\\2" DUNE_FIND_VERSION_NUMBER ${DUNE_FIND_VERSION})
+ string(STRIP ${DUNE_FIND_VERSION_NUMBER} DUNE_FIND_VERSION_NUMBER)
+ extract_major_minor_version("${DUNE_FIND_VERSION_NUMBER}" DUNE_FIND_VERSION)
+ set(DUNE_FIND_VERSION_STRING "${DUNE_FIND_VERSION_MAJOR}.${DUNE_FIND_VERSION_MINOR}.${DUNE_FIND_VERSION_REVISION}")
+ else()
+ set(DUNE_FIND_VERSION_STRING "0.0.0")
+ endif(DUNE_FIND_VERSION MATCHES "(>=|=|<=).*")
+ if(NOT ${module}_FOUND)
+ if(NOT (${module}_DIR OR ${module}_ROOT OR
+ "${CMAKE_PREFIX_PATH}" MATCHES ".*${module}.*"))
+ string(REPLACE ${ProjectName} ${module} ${module}_DIR
+ ${PROJECT_BINARY_DIR})
+ endif()
+ find_package(${module} NO_CMAKE_PACKAGE_REGISTRY)
+ endif(NOT ${module}_FOUND)
+ if(NOT ${module}_FOUND)
+ message(STATUS "No full CMake package configuration support available."
+ " Falling back to pkg-config.")
+ # use pkg-config
+ find_package(PkgConfig)
+ if(NOT PKG_CONFIG_FOUND AND required)
+ message(FATAL_ERROR "Could not find module ${module}. We tried to use"
+ "pkg-config but could not find it. ")
+ endif(NOT PKG_CONFIG_FOUND AND required)
+ pkg_check_modules (${module} ${required} ${module}${DUNE_FIND_VERSION})
+ set(${module}_FAKE_CMAKE_PKGCONFIG TRUE)
+ endif(NOT ${module}_FOUND)
+ if(${module}_FAKE_CMAKE_PKGCONFIG)
+ # compute the path to the libraries
+ if(${module}_LIBRARIES)
+ unset(_module_lib)
+ foreach(lib ${${module}_LIBRARIES})
+ foreach(libdir ${${module}_LIBRARY_DIRS})
+ if(EXISTS ${libdir}/lib${lib}.a)
+ set(_module_lib ${libdir}/lib${lib}.a)
+ set(_module_lib_static "STATIC")
+ endif()
+ if(EXISTS ${libdir}/lib${lib}.so)
+ set(_module_lib ${libdir}/lib${lib}.so)
+ set(_module_lib_static "")
+ endif()
+ if(_module_lib)
+ #import library
+ add_library(${lib} ${_module_lib_static} IMPORTED)
+ set_property(TARGET ${lib} APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG)
+ set_target_properties(${lib} PROPERTIES
+ IMPORTED_LINK_INTERFACE_LANGUAGES_NOCONFIG "CXX"
+ IMPORTED_LOCATION_NOCONFIG "${_module_lib}")
+ break()
+ endif(_module_lib)
+ endforeach(libdir ${${module}_LIBRARY_DIRS})
+ endforeach(lib ${${module}_LIBRARIES})
+ endif(${module}_LIBRARIES)
+ if(NOT ${module}_MODULE_PATH)
+ if(${module}_INCLUDE_DIRS)
+ list(GET ${module}_INCLUDE_DIRS 0 _dir)
+ if(EXISTS ${_dir}/../share/dune/cmake/modules)
+ set(${module}_MODULE_PATH ${_dir}/../share/dune/cmake/modules)
+ endif(EXISTS ${_dir}/../share/dune/cmake/modules)
+ endif(${module}_INCLUDE_DIRS)
+ endif(NOT ${module}_MODULE_PATH)
+ unset(${module}_FAKE_CMAKE_PKGCONFIG)
+ endif(${module}_FAKE_CMAKE_PKGCONFIG)
+ if(${module}_FOUND)
+ # parse other module's dune.module file to generate variables for config.h
+ unset(${module}_dune_module)
+ foreach(_dune_module_file ${${module}_PREFIX}/dune.module
+ ${${module}_PREFIX}/lib/dunecontrol/${module}/dune.module)
+ if(EXISTS ${_dune_module_file})
+ get_filename_component(_dune_module_file_path ${_dune_module_file} PATH)
+ dune_module_information(${_dune_module_file_path})# QUIET)
+ set(${module}_dune_module 1)
+ set(DUNE_FIND_MOD_VERSION_STRING "${DUNE_VERSION_MAJOR}.${DUNE_VERSION_MINOR}.${DUNE_VERSION_REVISION}")
+ # check whether dependency mathes version requirement
+ unset(module_version_wrong)
+ if(DUNE_FIND_VERSION_OP MATCHES ">=")
+ if(NOT (DUNE_FIND_MOD_VERSION_STRING VERSION_EQUAL DUNE_FIND_VERSION_STRING OR
+ DUNE_FIND_MOD_VERSION_STRING VERSION_GREATER DUNE_FIND_VERSION_STRING))
+ set(module_version_wrong 1)
+ endif()
+ elseif(DUNE_FIND_VERSION_OP MATCHES "<=")
+ if(NOT (DUNE_FIND_MOD_VERSION_STRING VERSION_EQUAL DUNE_FIND_VERSION_STRING OR
+ DUNE_FIND_MOD_VERSION_STRING VERSION_LESS DUNE_FIND_VERSION_STRING))
+ set(module_version_wrong 1)
+ endif()
+ elseif(DUNE_FIND_VERSION_OP MATCHES "=" AND
+ NOT (DUNE_FIND_MOD_VERSION_STRING VERSION_EQUAL DUNE_FIND_VERSION_STRING))
+ set(module_version_wrong 1)
+ endif()
+ endif(EXISTS ${_dune_module_file})
+ endforeach()
+ if(NOT ${module}_dune_module)
+ message(FATAL_ERROR "Could not find dune.module file for module ${module} "
+ "in ${${module}_PREFIX}, ${${module}_PREFIX}/lib/dunecontrol/${module}/")
+ endif(NOT ${module}_dune_module)
+ if(module_version_wrong)
+ message(FATAL_ERROR "Could not find requested version of module ${module}. "
+ "Requested version was ${DUNE_FIND_VERSION}, found version is ${DUNE_FIND_MOD_VERSION_STRING}")
+ endif()
+ else(${module}_FOUND)
+ if(required)
+ message(FATAL_ERROR "Could not find required module ${module}.")
+ endif(required)
+ endif(${module}_FOUND)
+ set(DUNE_${module}_FOUND ${${module}_FOUND})
+endmacro(find_dune_package module)
+
+macro(extract_line HEADER OUTPUT FILE_CONTENT)
+ set(REGEX "${HEADER}[ ]*[^\n]+")
+ string(REGEX MATCH ${REGEX} OUTPUT1 "${FILE_CONTENT}")
+ if(OUTPUT1)
+ set(REGEX "^[ ]*${HEADER}[ ]*(.+)[ ]*$")
+ string(REGEX REPLACE ${REGEX} "\\1" ${OUTPUT} "${OUTPUT1}")
+ else(OUTPUT1)
+ set(OUTPUT OUTPUT-NOTFOUND)
+ endif(OUTPUT1)
+endmacro(extract_line)
+
+macro(split_module_version STRING MODULES VERSIONS)
+ set(REGEX "[a-zA-Z-]+[ ]*(\\([ ]*([^ ]+)?[ ]*[^ ]+[ ]*\\))?")
+ #set(REGEX "dune")
+ string(REGEX MATCHALL "${REGEX}" matches "${STRING}")
+ set(${MODULES} "")
+ set(${VERSIONS} "")
+ foreach(i ${matches})
+ string(REGEX REPLACE "^([a-zA-Z-]+).*$" "\\1" mod ${i})
+ string(REGEX MATCH "\\([ ]*(([^ ]+)?[ ]*[^ ]+)[ ]*\\)" have_version
+ ${i})
+ if(have_version)
+ string(REGEX REPLACE "^\\([ ]*([^ ]*[ ]*[^ ]+)[ ]*\\)$" "\\1"
+ version ${have_version})
+ else(have_version)
+ set(version " ") # Mark as no version requested.
+ # Having a space is mandatory as we will append it to a list
+ # and an empty string will not be treated as entry we append to it.
+ endif(have_version)
+ list(APPEND ${MODULES} ${mod})
+ list(APPEND ${VERSIONS} ${version})
+ endforeach(i "${matches}")
+endmacro(split_module_version)
+
+function(convert_deps_to_list var)
+ string(REGEX REPLACE "([a-zA-Z\\)]) ([a-zA-Z])" "\\1;\\2" ${var} ${${var}})
+ set(${var} ${${var}} PARENT_SCOPE)
+endfunction(convert_deps_to_list var)
+
+#
+# extracts major, minor, and revision from version string
+#
+function(extract_major_minor_version version_string varname)
+ string(REGEX REPLACE "([0-9]+).*" "\\1" ${varname}_MAJOR "${version_string}")
+ string(REGEX REPLACE "[0-9]+\\.([0-9]+).*" "\\1" ${varname}_MINOR "${version_string}")
+ string(REGEX REPLACE "[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" ${varname}_REVISION "${version_string}")
+ set(${varname}_MAJOR "${${varname}_MAJOR}" PARENT_SCOPE) # make variable accessible in parent scope
+
+ # remove false matches in version string and export to parent scop
+ string(REGEX MATCH "[^0-9]" NON_NUMBER_CHARACTER "${${varname}_MINOR}")
+ if(NON_NUMBER_CHARACTER)
+ set(${varname}_MINOR "0" PARENT_SCOPE)
+ else(NON_NUMBER_CHARACTER)
+ set(${varname}_MINOR ${${varname}_MINOR} PARENT_SCOPE)
+ endif(NON_NUMBER_CHARACTER)
+ string(REGEX MATCH "[^0-9]" NON_NUMBER_CHARACTER "${${varname}_REVISION}")
+ if(NON_NUMBER_CHARACTER)
+ set(${varname}_REVISION "0" PARENT_SCOPE)
+ else(NON_NUMBER_CHARACTER)
+ set(${varname}_REVISION ${${varname}_REVISION} PARENT_SCOPE)
+ endif(NON_NUMBER_CHARACTER)
+endfunction(extract_major_minor_version version_string varname)
+
+# add dune-common version from dune.module to config.h
+# optional second argument is verbosity
+macro(dune_module_information MODULE_DIR)
+ file(READ "${MODULE_DIR}/dune.module" DUNE_MODULE)
+
+ # find version strings
+ extract_line("Version:" MODULE_LINE "${DUNE_MODULE}")
+ if(NOT MODULE_LINE MATCHES ".+")
+ message(FATAL_ERROR "${MODULE_DIR}/dune.module is missing a version.")
+ endif(NOT MODULE_LINE MATCHES ".+")
+
+ string(REGEX REPLACE ".*Version:[ ]*([^ \n]+).*" "\\1" DUNE_MOD_VERSION "${MODULE_LINE}")
+ extract_major_minor_version("${DUNE_MOD_VERSION}" DUNE_VERSION)
+
+ # find strings for module name, maintainer
+ # 1. Check for line starting with Module
+ extract_line("Module:" DUNE_MOD_NAME "${DUNE_MODULE}")
+ if(NOT DUNE_MOD_NAME)
+ message(FATAL_ERROR "${MODULE_DIR}/dune.module is missing a module name.")
+ endif(NOT DUNE_MOD_NAME)
+
+ # 2. Check for line starting with Maintainer
+ extract_line("Maintainer:" DUNE_MAINTAINER "${DUNE_MODULE}")
+ if(NOT DUNE_MAINTAINER)
+ message(FATAL_ERROR "${MODULE_DIR}/dune.module is missing a maintainer.")
+ endif(NOT DUNE_MAINTAINER)
+
+ # 3. Check for line starting with Depends
+ extract_line("Depends:" ${DUNE_MOD_NAME}_DEPENDS "${DUNE_MODULE}")
+ if(${DUNE_MOD_NAME}_DEPENDS)
+ split_module_version(${${DUNE_MOD_NAME}_DEPENDS} ${DUNE_MOD_NAME}_DEPENDS_MODULE ${DUNE_MOD_NAME}_DEPENDS_VERSION)
+ foreach(_mod ${${DUNE_MOD_NAME}_DEPENDS})
+ set(${_mod}_REQUIRED REQUIRED)
+ endforeach(_mod ${${DUNE_MOD_NAME}_DEPENDS})
+ convert_deps_to_list(${DUNE_MOD_NAME}_DEPENDS)
+ if(NOT ("${ARGV1}" STREQUAL QUIET))
+ message(STATUS "Dependencies for ${DUNE_MOD_NAME}: ${${DUNE_MOD_NAME}_DEPENDS}")
+ endif(NOT ("${ARGV1}" STREQUAL QUIET))
+ endif(${DUNE_MOD_NAME}_DEPENDS)
+
+ # 4. Check for line starting with Suggests
+ extract_line("Suggests:" ${DUNE_MOD_NAME}_SUGGESTS "${DUNE_MODULE}")
+ if(${DUNE_MOD_NAME}_SUGGESTS)
+ split_module_version(${${DUNE_MOD_NAME}_SUGGESTS} ${DUNE_MOD_NAME}_SUGGESTS_MODULE ${DUNE_MOD_NAME}_SUGGESTS_VERSION)
+ convert_deps_to_list(${DUNE_MOD_NAME}_SUGGESTS)
+ if(NOT ("${ARGV1}" STREQUAL QUIET))
+ message(STATUS "Suggestions for ${DUNE_MOD_NAME}: ${${DUNE_MOD_NAME}_SUGGESTS}")
+ endif(NOT ("${ARGV1}" STREQUAL QUIET))
+ endif(${DUNE_MOD_NAME}_SUGGESTS)
+
+ dune_module_to_uppercase(DUNE_MOD_NAME_UPPERCASE ${DUNE_MOD_NAME})
+
+ # set module version
+ set(${DUNE_MOD_NAME_UPPERCASE}_VERSION "${DUNE_MOD_VERSION}")
+ set(${DUNE_MOD_NAME_UPPERCASE}_VERSION_MAJOR "${DUNE_VERSION_MAJOR}")
+ set(${DUNE_MOD_NAME_UPPERCASE}_VERSION_MINOR "${DUNE_VERSION_MINOR}")
+ set(${DUNE_MOD_NAME_UPPERCASE}_VERSION_REVISION "${DUNE_VERSION_REVISION}")
+endmacro(dune_module_information)
+
+macro(dune_process_dependency_leafs modules versions is_required next_level_deps
+ next_level_sugs)
+ # modules, and versions are not real variables, make them one
+ set(mmodules ${modules})
+ set(mversions ${versions})
+ list(LENGTH mmodules mlength)
+ list(LENGTH mversions vlength)
+ if(NOT mlength EQUAL vlength)
+ message(STATUS "mmodules=${mmodules} modules=${modules}")
+ message(STATUS "mversions=${mversions} versions=${mversions}")
+ message(FATAL_ERROR "List of modules and versions do not have the same length!")
+ endif(NOT mlength EQUAL vlength)
+ if(mlength GREATER 0)
+ math(EXPR length "${mlength}-1")
+ foreach(i RANGE 0 ${length})
+ list(GET mmodules ${i} _mod)
+ list(GET mversions ${i} _ver)
+ find_dune_package(${_mod} ${is_required} VERSION "${_ver}")
+ set(${_mod}_SEARCHED ON)
+ if(NOT "${is_required}" STREQUAL "")
+ set(${_mod}_REQUIRED ON)
+ set(${next_level_deps} ${${_mod}_DEPENDS} ${${next_level_deps}})
+ else(NOT "${is_required}" STREQUAL "")
+ set(${next_level_sugs} ${${_mod}_DEPENDS} ${${next_level_sugs}})
+ endif(NOT "${is_required}" STREQUAL "")
+ set(${next_level_sugs} ${${_mod}_SUGGESTS} ${${next_level_sugs}})
+ endforeach(i RANGE 0 ${length})
+ endif(mlength GREATER 0)
+ if(${next_level_sugs})
+ list(REMOVE_DUPLICATES ${next_level_sugs})
+ endif(${next_level_sugs})
+ if(${next_level_deps})
+ list(REMOVE_DUPLICATES ${next_level_deps})
+ endif(${next_level_deps})
+endmacro(dune_process_dependency_leafs)
+
+function(remove_processed_modules modules versions is_required)
+ list(LENGTH ${modules} mlength)
+ if(mlength GREATER 0)
+ math(EXPR length "${mlength}-1")
+ foreach(i RANGE ${length} 0 -1)
+ list(GET ${modules} ${i} _mod)
+ if(${_mod}_SEARCHED)
+ list(REMOVE_AT ${modules} ${i})
+ list(REMOVE_AT ${versions} ${i})
+ if(is_required AND NOT ${_mod}_REQUIRED AND NOT ${_mod}_FOUND)
+ message(FATAL_ERROR "Required module ${_mod} not found!")
+ endif(is_required AND NOT ${_mod}_REQUIRED AND NOT ${_mod}_FOUND)
+ endif(${_mod}_SEARCHED)
+ endforeach(i RANGE 0 ${length})
+ endif(mlength GREATER 0)
+ set(${modules} ${${modules}} PARENT_SCOPE)
+ set(${versions} ${${versions}} PARENT_SCOPE)
+endfunction(remove_processed_modules modules versions is_required)
+
+macro(dune_create_dependency_leafs depends depends_versions suggests suggests_versions)
+ set(deps "")
+ set(sugs "")
+ #Process dependencies
+ if(NOT "${depends}" STREQUAL "")
+ dune_process_dependency_leafs("${depends}" "${depends_versions}" REQUIRED deps sugs)
+ endif(NOT "${depends}" STREQUAL "")
+ # Process suggestions
+ if(NOT "${suggests}" STREQUAL "")
+ dune_process_dependency_leafs("${suggests}" "${suggests_versions}" "" deps sugs)
+ endif(NOT "${suggests}" STREQUAL "")
+ split_module_version("${deps}" next_mod_depends next_depends_versions)
+ split_module_version("${sugs}" next_mod_suggests next_suggests_versions)
+ set(ALL_DEPENDENCIES ${ALL_DEPENDENCIES} ${next_mod_depends} ${next_mod_suggests})
+ # Move to next level
+ if(next_mod_suggests OR next_mod_depends)
+ dune_create_dependency_leafs("${next_mod_depends}" "${next_depends_versions}"
+ "${next_mod_suggests}" "${next_suggests_versions}")
+ endif(next_mod_suggests OR next_mod_depends)
+endmacro(dune_create_dependency_leafs)
+
+macro(dune_create_dependency_tree)
+ if(${dune-common_MODULE_PATH})
+ list(REMOVE_ITEM CMAKE_MODULE_PATH ${dune-common_MODULE_PATH})
+ endif(${dune-common_MODULE_PATH})
+ list(FIND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules start)
+ set(ALL_DEPENDENCIES "")
+ if(${ProjectName}_DEPENDS_MODULE OR ${ProjectName}_SUGGESTS_MODULE)
+ set(ALL_DEPENDENCIES ${${ProjectName}_DEPENDS_MODULE} ${${ProjectName}_SUGGESTS_MODULE})
+ dune_create_dependency_leafs("${${ProjectName}_DEPENDS_MODULE}" "${${ProjectName}_DEPENDS_VERSION}"
+ "${${ProjectName}_SUGGESTS_MODULE}" "${${ProjectName}_SUGGESTS_VERSION}")
+ endif(${ProjectName}_DEPENDS_MODULE OR ${ProjectName}_SUGGESTS_MODULE)
+ set(_my_path "")
+ if(ALL_DEPENDENCIES)
+ # Reverse the order of the modules and remove duplicates
+ # At end of this clause we have have a list modules
+ # where for each entry all dependencies are before the
+ # module in the list.
+ set(NEW_ALL_DEPS "")
+ list(LENGTH ALL_DEPENDENCIES length)
+ if(length GREATER 0)
+ math(EXPR length "${length}-1")
+ list(GET ALL_DEPENDENCIES ${length} _mod)
+ set(${_mod}_cmake_path_processed 1)
+ set(_my_path ${${_mod}_MODULE_PATH})
+ list(APPEND NEW_ALL_DEPS ${_mod})
+ if(length GREATER 0)
+ math(EXPR length "${length}-1")
+ foreach(i RANGE ${length} 0 -1)
+ list(GET ALL_DEPENDENCIES ${i} _mod)
+ if(NOT ${_mod}_cmake_path_processed)
+ set(${_mod}_cmake_path_processed 1)
+ if(${_mod}_MODULE_PATH)
+ list(INSERT _my_path 0 ${${_mod}_MODULE_PATH})
+ endif(${_mod}_MODULE_PATH)
+ list(APPEND NEW_ALL_DEPS ${_mod})
+ endif(NOT ${_mod}_cmake_path_processed)
+ endforeach(i RANGE ${length} 0 -1)
+ endif(length GREATER 0)
+ list(LENGTH CMAKE_MODULE_PATH length)
+ math(EXPR length "${length}-1")
+ if(start EQUAL -1)
+ list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules ${_my_path})
+ else(start EQUAL -1)
+ if(start EQUAL ${length})
+ list(APPEND CMAKE_MODULE_PATH ${_my_path})
+ else(start EQUAL ${length})
+ if(_my_path)
+ list(INSERT CMAKE_MODULE_PATH ${start} ${_my_path})
+ endif(_my_path)
+ endif(start EQUAL ${length})
+ endif(start EQUAL -1)
+ endif(length GREATER 0)
+ set(ALL_DEPENDENCIES ${NEW_ALL_DEPS})
+ endif(ALL_DEPENDENCIES)
+endmacro(dune_create_dependency_tree)
+
+# Converts a module name given by _dune_module into a string _macro_name
+# where all dashes (-) are removed and letters after a dash are capitalized
+# Example: dune-grid-howto -> DuneGridHowto
+macro(dune_module_to_macro _macro_name _dune_module)
+ set(${_macro_name} "")
+ set(_rest "${_dune_module}")
+ string(FIND "${_rest}" "-" _found)
+ while(_found GREATER -1)
+ string(REGEX REPLACE "([^-]*)-.*" "\\1" _first_part
+ "${_rest}")
+ string(REGEX REPLACE "[^-]*-(.*)" "\\1" _rest
+ "${_rest}")
+ string(SUBSTRING "${_first_part}" 0 1 _first_letter)
+ string(SUBSTRING "${_first_part}" 1 -1 _rest_first_part)
+ string(TOUPPER "${_first_letter}" _first_letter)
+ set(${_macro_name} "${${_macro_name}}${_first_letter}${_rest_first_part}")
+ string(FIND "${_rest}" "-" _found)
+ endwhile(_found GREATER -1)
+ string(LENGTH "${_rest}" _length)
+ string(SUBSTRING "${_rest}" 0 1 _first_letter)
+ string(SUBSTRING "${_rest}" 1 -1 _rest)
+ string(TOUPPER "${_first_letter}" _first_letter)
+ set(${_macro_name} "${${_macro_name}}${_first_letter}${_rest}")
+endmacro(dune_module_to_macro _macro_name _dune_module)
+
+macro(dune_process_dependency_macros)
+ foreach(_mod ${ALL_DEPENDENCIES} ${ProjectName})
+ if(NOT ${_mod}_PROCESSED)
+ # module not processed yet
+ set(${_mod}_PROCESSED ${_mod})
+ # Search for a cmake files containing tests and directives
+ # specific to this module
+ dune_module_to_macro(_cmake_mod_name "${_mod}")
+ set(_macro "${_cmake_mod_name}Macros")
+ set(_mod_cmake _mod_cmake-NOTFOUND) # Prevent false positives due to caching
+ find_file(_mod_cmake
+ ${_macro}.cmake
+ ${CMAKE_MODULE_PATH}
+ NO_DEFAULT_PATH)
+ if(_mod_cmake)
+ message(STATUS "Performing tests specific to ${_mod} from file ${_mod_cmake}.")
+ include(${_mod_cmake})
+ endif(_mod_cmake)
+ dune_module_to_uppercase(_upper_case "${_mod}")
+ if(${_mod}_INCLUDE_DIRS)
+ message(STATUS "Setting ${_mod}_INCLUDE_DIRS=${${_mod}_INCLUDE_DIRS}")
+ include_directories("${${_mod}_INCLUDE_DIRS}")
+ endif(${_mod}_INCLUDE_DIRS)
+ if(${_mod}_LIBRARIES)
+ message(STATUS "Setting ${_mod}_LIBRARIES=${${_mod}_LIBRARIES}")
+ foreach(_lib ${${_mod}_LIBRARIES})
+ list(INSERT DUNE_DEFAULT_LIBS 0 "${_lib}")
+ list(INSERT DUNE_LIBS 0 "${_lib}")
+ endforeach(_lib ${${_mod}_LIBRARIES})
+ endif(${_mod}_LIBRARIES)
+
+ #update ALL_PKG_FLAGS
+ foreach(dir ${${_mod}_INCLUDE_DIRS})
+ set_property(GLOBAL APPEND PROPERTY ALL_PKG_FLAGS "-I${dir}")
+ endforeach()
+ endif(NOT ${_mod}_PROCESSED)
+ endforeach(_mod DEPENDENCIES)
+endmacro(dune_process_dependency_macros)
+
+# macro that should be called near the begin of the top level CMakeLists.txt.
+# Namely it sets up the module, defines basic variables and manages
+# depedencies.
+# Don't forget to call finalize_dune_project afterwards.
+macro(dune_project)
+ # extract information from dune.module
+ dune_module_information(${CMAKE_SOURCE_DIR})
+ set(ProjectName "${DUNE_MOD_NAME}")
+ set(ProjectVersion "${DUNE_MOD_VERSION}")
+ set(ProjectVersionString "${DUNE_VERSION_MAJOR}.${DUNE_VERSION_MINOR}.${DUNE_VERSION_REVISION}")
+ set(ProjectVersionMajor "${DUNE_VERSION_MAJOR}")
+ set(ProjectVersionMinor "${DUNE_VERSION_MINOR}")
+ set(ProjectMaintainerEmail "${DUNE_MAINTAINER}")
+
+ define_property(GLOBAL PROPERTY DUNE_MODULE_LIBRARIES
+ BRIEF_DOCS "List of libraries of the module. DO NOT EDIT!"
+ FULL_DOCS "List of libraries of the module. Used to generate CMake's package configuration files. DO NOT EDIT!")
+ dune_create_dependency_tree()
+
+ # assert the project names matches
+ if(NOT (ProjectName STREQUAL CMAKE_PROJECT_NAME))
+ message(FATAL_ERROR "Module name from dune.module does not match the name given in CMakeLists.txt.")
+ endif(NOT (ProjectName STREQUAL CMAKE_PROJECT_NAME))
+
+ # optional Fortran support
+ include(LanguageSupport)
+ workaround_9220(Fortran Fortran_Works)
+ if(Fortran_Works)
+ enable_language(Fortran OPTIONAL)
+ endif(Fortran_Works)
+
+ option(DUNE_USE_ONLY_STATIC_LIBS "If set to ON, we will force static linkage everywhere" OFF)
+ if(DUNE_USE_ONLY_STATIC_LIBS)
+ if(BUILD_SHARED_LIBS)
+ message(FATAL_ERROR "Your requesting to use only static libraries "
+ "(DUNE_USE_ONLY_STATIC_LIBS==True) while at same time requesting to "
+ "build shared libraries (BUILD_SHARED_LIBS==True). This is a "
+ "contradiction!")
+ endif(BUILD_SHARED_LIBS)
+ endif(DUNE_USE_ONLY_STATIC_LIBS)
+ option(DUNE_BUILD_BOTH_LIBS "If set to ON, shared and static libs will be built"
+ ${_default_enable_static})
+
+ if(DUNE_USE_ONLY_STATIC_LIBS)
+ # Use only static libraries.
+ # We do this by overriding the library suffixes.
+ set( BLA_STATIC 1)
+ set( _dune_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ if (WIN32)
+ set(CMAKE_FIND_LIBRARY_SUFFIXES .lib ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ endif (WIN32)
+ if (APPLE)
+ set(CMAKE_FIND_LIBRARY_SUFFIXES .lib ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ else (APPLE)
+ set(CMAKE_FIND_LIBRARY_SUFFIXES .a )
+ endif (APPLE)
+ endif(DUNE_USE_ONLY_STATIC_LIBS)
+
+ # set required compiler flags for C++11 (former C++0x)
+ include(CheckCXX11Features)
+
+ include(DuneCxaDemangle)
+
+ # search for headers
+ include(CheckIncludeFile)
+ include(CheckIncludeFileCXX)
+ check_include_file("malloc.h" HAVE_MALLOC_H)
+ check_include_file("stdint.h" HAVE_STDINT_H)
+ check_include_file_cxx("memory" HAVE_MEMORY)
+ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -DHAVE_MEMORY=${HAVE_MEMORY}")
+
+ # set include path and link path for the current project.
+ include_directories("${CMAKE_BINARY_DIR}")
+ include_directories("${CMAKE_SOURCE_DIR}")
+ include_directories("${CMAKE_CURRENT_BINARY_DIR}")
+ include_directories("${CMAKE_CURRENT_SOURCE_DIR}")
+ add_definitions(-DHAVE_CONFIG_H)
+
+ # Search for MPI and set the relevant variables.
+ include(DuneMPI)
+
+ # Make calling fortran routines from C/C++ possible
+ if(Fortran_Works)
+ include(FortranCInterface)
+ FortranCInterface_VERIFY(CXX)
+ # Write FC.h header containing information about
+ # how to call fortran routined.
+ # It will be included in config.h
+ FortranCInterface_HEADER(FC.h MACRO_NAMESPACE "FC_")
+ else(Fortran_Works)
+ # Write empty FC.h header
+ file(WRITE ${CMAKE_BINARY_DIR}/FC.h "")
+ endif(Fortran_Works)
+
+ # Create custom target for building the documentation
+ # and provide macros for installing the docs and force
+ # building them before.
+ include(DuneDoc)
+
+ # activate testing the DUNE way
+ include(DuneTests)
+
+ # activate pkg-config
+ include(DunePkgConfig)
+
+ # Process the macros provided by the dependencies and ourself
+ dune_process_dependency_macros()
+
+ include(GNUInstallDirs)
+ # Set variable where the cmake modules will be installed.
+ # Thus the user can override it and for example install
+ # directly into the CMake installation. We use a cache variable
+ # that is overridden by a local variable of the same name if
+ # the user does not explicitely set a value for it. Thus the value
+ # will automatically change if the user changes CMAKE_INSTALL_DATAROOTDIR
+ # or CMAKE_INSTALL_PREFIX
+ if(NOT DUNE_INSTALL_MODULEDIR)
+ set(DUNE_INSTALL_MODULEDIR ""
+ CACHE PATH
+ "Installation directory for CMake modules. Default is \${CMAKE_INSTALL_DATAROOTDIR}/dune/cmake/modules when not set explicitely")
+ set(DUNE_INSTALL_MODULEDIR ${CMAKE_INSTALL_DATAROOTDIR}/dune/cmake/modules)
+ endif(NOT DUNE_INSTALL_MODULEDIR)
+ if(NOT DUNE_INSTALL_NONOBJECTLIBDIR)
+ set(DUNE_INSTALL_NONOBJECTLIBDIR ""
+ CACHE PATH
+ "Installation directory for libraries that are not architecture dependent. Default is lib when not set explicitely")
+ set(DUNE_INSTALL_NONOBJECTLIBDIR lib)
+ endif(NOT DUNE_INSTALL_NONOBJECTLIBDIR)
+ # set up make headercheck
+ include(Headercheck)
+ setup_headercheck()
+endmacro(dune_project)
+
+# create a new config.h file and overwrite the existing one
+macro(dune_regenerate_config_cmake)
+ set(CONFIG_H_CMAKE_FILE "${CMAKE_BINARY_DIR}/config.h.cmake")
+ if(EXISTS ${CMAKE_SOURCE_DIR}/config.h.cmake)
+ file(READ ${CMAKE_SOURCE_DIR}/config.h.cmake _file)
+ string(REGEX MATCH
+ "/[\\*/][ ]*begin[ ]+${ProjectName}.*\\/[/\\*][ ]*end[ ]*${ProjectName}[^\\*]*\\*/"
+ _myfile "${_file}")
+ endif(EXISTS ${CMAKE_SOURCE_DIR}/config.h.cmake)
+ # overwrite file with new content
+ file(WRITE ${CONFIG_H_CMAKE_FILE} "/* config.h. Generated from config.h.cmake by CMake.
+ It was generated from config.h.cmake which in turn is generated automatically
+ from the config.h.cmake files of modules this module depends on. */"
+ )
+
+ # define that we found this module
+ set(${ProjectName}_FOUND 1)
+ foreach(_dep ${ProjectName} ${ALL_DEPENDENCIES})
+ dune_module_to_uppercase(upper ${_dep})
+ set(HAVE_${upper} ${${_dep}_FOUND})
+ file(APPEND ${CONFIG_H_CMAKE_FILE}
+ "\n\n/* Define to 1 if you have module ${_dep} available */
+#cmakedefine01 HAVE_${upper}\n")
+ endforeach(_dep ${ProjectName} ${ALL_DEPENDENCIES})
+
+ # add previous module specific section
+ foreach(_dep ${ALL_DEPENDENCIES})
+ foreach(_mod_conf_file ${${_dep}_PREFIX}/config.h.cmake
+ ${${_dep}_PREFIX}/share/${_dep}/config.h.cmake)
+ if(EXISTS ${_mod_conf_file})
+ file(READ "${_mod_conf_file}" _file)
+ string(REGEX REPLACE
+ ".*/\\*[ ]*begin[ ]+${_dep}[^\\*]*\\*/(.*)/[/\\*][ ]*end[ ]*${_dep}[^\\*]*\\*/" "\\1"
+ _tfile "${_file}")
+ # strip the private section
+ string(REGEX REPLACE "(.*)/[\\*][ ]*begin private.*/[\\*][ ]*end[ ]*private[^\\*]\\*/(.*)" "\\1\\2" _file "${_tfile}")
+ file(APPEND ${CONFIG_H_CMAKE_FILE} "${_file}")
+ endif(EXISTS ${_mod_conf_file})
+ endforeach()
+ endforeach(_dep ${ALL_DEPENDENCIES})
+ # parse again dune.module file of current module to set PACKAGE_* variables
+ dune_module_information(${CMAKE_SOURCE_DIR} QUIET)
+ file(APPEND ${CONFIG_H_CMAKE_FILE} "\n${_myfile}")
+endmacro(dune_regenerate_config_cmake)
+
+# macro that should be called at the end of the top level CMakeLists.txt.
+# Namely it creates config.h and the cmake-config files,
+# some install directives and exports the module.
+macro(finalize_dune_project)
+ #configure all headerchecks
+ finalize_headercheck()
+
+ #create cmake-config files for installation tree
+ include(DuneCMakePackageConfigHelpers)
+ include(GNUInstallDirs)
+ set(DOXYSTYLE_DIR ${CMAKE_INSTALL_DATAROOTDIR}/dune-common/doc/doxygen/)
+ set(SCRIPT_DIR ${CMAKE_INSTALL_DATAROOTDIR}/dune/cmake/scripts)
+
+ if(NOT EXISTS ${PROJECT_SOURCE_DIR}/cmake/pkg/${ProjectName}-config.cmake.in)
+ # Generate a standard cmake package configuration file
+ file(WRITE ${PROJECT_BINARY_DIR}/CMakeFiles/${ProjectName}-config.cmake.in
+"if(NOT @ProjectName@_FOUND)
+@PACKAGE_INIT@
+
+#report other information
+set_and_check(@ProjectName@_PREFIX \"\${PACKAGE_PREFIX_DIR}\")
+set_and_check(@ProjectName@_INCLUDE_DIRS \"@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@\")
+set(@ProjectName@_CXX_FLAGS \"@CMAKE_CXX_FLAGS@\")
+set(@ProjectName@_CXX_FLAGS_DEBUG \"@CMAKE_CXX_FLAGS_DEBUG@\")
+set(@ProjectName@_CXX_FLAGS_MINSIZEREL \"@CMAKE_CXX_FLAGS_MINSIZEREL@\")
+set(@ProjectName@_CXX_FLAGS_RELEASE \"@CMAKE_CXX_FLAGS_RELEASE@\")
+set(@ProjectName@_CXX_FLAGS_RELWITHDEBINFO \"@CMAKE_CXX_FLAGS_RELWITHDEBINFO@\")
+set(@ProjectName@_DEPENDS \"@@ProjectName@_DEPENDS@\")
+set(@ProjectName@_SUGGESTS \"@@ProjectName@_SUGGESTS@\")
+set(@ProjectName@_MODULE_PATH \"@PACKAGE_DUNE_INSTALL_MODULEDIR@\")
+set(@ProjectName@_LIBRARIES \"@DUNE_MODULE_LIBRARIES@\")
+#import the target
+if(@ProjectName@_LIBRARIES)
+ get_filename_component(_dir \"\${CMAKE_CURRENT_LIST_FILE}\" PATH)
+ include(\"\${_dir}/@ProjectName@-targets.cmake\")
+endif(@ProjectName@_LIBRARIES)
+endif(NOT @ProjectName@_FOUND)")
+ set(CONFIG_SOURCE_FILE ${PROJECT_BINARY_DIR}/CMakeFiles/${ProjectName}-config.cmake.in)
+ else(NOT EXISTS ${PROJECT_SOURCE_DIR}/cmake/pkg/${ProjectName}-config.cmake.in)
+ set(CONFIG_SOURCE_FILE ${PROJECT_SOURCE_DIR}/cmake/pkg/${ProjectName}-config.cmake.in)
+ endif(NOT EXISTS ${PROJECT_SOURCE_DIR}/cmake/pkg/${ProjectName}-config.cmake.in)
+ get_property(DUNE_MODULE_LIBRARIES GLOBAL PROPERTY DUNE_MODULE_LIBRARIES)
+
+ # compute under which libdir the package configuration files are to be installed.
+ # If the module installs an object library we use CMAKE_INSTALL_LIBDIR
+ # to capture the multiarch triplet of Debian/Ubuntu.
+ # Otherwise we fall back to DUNE_INSTALL_NONOBJECTLIB which is lib
+ # if not set otherwise.
+ get_property(DUNE_MODULE_LIBRARIES GLOBAL PROPERTY DUNE_MODULE_LIBRARIES)
+ if(DUNE_MODULE_LIBRARIES)
+ set(DUNE_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR})
+ else(DUNE_MODULE_LIBRARIES)
+ set(DUNE_INSTALL_LIBDIR ${DUNE_INSTALL_NONOBJECTLIBDIR})
+ endif(DUNE_MODULE_LIBRARIES)
+
+ configure_package_config_file(${CONFIG_SOURCE_FILE}
+ ${PROJECT_BINARY_DIR}/cmake/pkg/${ProjectName}-config.cmake
+ INSTALL_DESTINATION ${DUNE_INSTALL_LIBDIR}/cmake/${ProjectName}
+ PATH_VARS CMAKE_INSTALL_DATAROOTDIR DUNE_INSTALL_MODULEDIR CMAKE_INSTALL_INCLUDEDIR
+ DOXYSTYLE_DIR SCRIPT_DIR)
+
+
+ #create cmake-config files for build tree
+ set(PACKAGE_CMAKE_INSTALL_INCLUDEDIR ${PROJECT_SOURCE_DIR})
+ set(PACKAGE_CMAKE_INSTALL_DATAROOTDIR ${PROJECT_BINARY_DIR})
+ set(PACKAGE_DOXYSTYLE_DIR ${PROJECT_SOURCE_DIR}/doc/doxygen)
+ set(PACKAGE_SCRIPT_DIR ${PROJECT_SOURCE_DIR}/cmake/scripts)
+ set(PACKAGE_DUNE_INSTALL_MODULEDIR ${PROJECT_SOURCE_DIR}/cmake/modules)
+ set(PACKAGE_PREFIX_DIR ${PROJECT_BINARY_DIR})
+ set(PACKAGE_INIT "# Set prefix to source dir
+set(PACKAGE_PREFIX_DIR ${PROJECT_SOURCE_DIR})
+macro(set_and_check _var _file)
+ set(\${_var} \"\${_file}\")
+ if(NOT EXISTS \"\${_file}\")
+ message(FATAL_ERROR \"File or directory \${_file} referenced by variable \${_var} does not exist !\")
+ endif()
+endmacro()")
+ configure_file(
+ ${CONFIG_SOURCE_FILE}
+ ${PROJECT_BINARY_DIR}/${ProjectName}-config.cmake @ONLY)
+
+ if(NOT EXISTS ${PROJECT_SOURCE_DIR}/${ProjectName}-config-version.cmake.in)
+ file(WRITE ${PROJECT_BINARY_DIR}/CMakeFiles/${ProjectName}-config-version.cmake.in
+"set(PACKAGE_VERSION \"@ProjectVersionString@\")
+
+if(\"\${PACKAGE_FIND_VERSION_MAJOR}\" EQUAL \"@ProjectVersionMajor@\" AND
+ \"\${PACKAGE_FIND_VERSION_MINOR}\" EQUAL \"@ProjectVersionMinor@\")
+ set (PACKAGE_VERSION_COMPATIBLE 1) # compatible with newer
+ if (\"\${PACKAGE_FIND_VERSION}\" VERSION_EQUAL \"@ProjectVersionString@\")
+ set(PACKAGE_VERSION_EXACT 1) #exact match for this version
+ endif()
+endif()
+")
+ set(CONFIG_VERSION_FILE ${PROJECT_BINARY_DIR}/CMakeFiles/${ProjectName}-config-version.cmake.in)
+ else(NOT EXISTS ${PROJECT_SOURCE_DIR}/${ProjectName}-config-version.cmake.in)
+ set(CONFIG_VERSION_FILE ${PROJECT_SOURCE_DIR}/${ProjectName}-config-version.cmake.in)
+ endif(NOT EXISTS ${PROJECT_SOURCE_DIR}/${ProjectName}-config-version.cmake.in)
+ configure_file(
+ ${CONFIG_VERSION_FILE}
+ ${PROJECT_BINARY_DIR}/${ProjectName}-config-version.cmake @ONLY)
+
+ #install dune.module file
+ install(FILES dune.module DESTINATION ${DUNE_INSTALL_NONOBJECTLIBDIR}/dunecontrol/${ProjectName})
+
+ # install cmake-config files
+ install(FILES ${PROJECT_BINARY_DIR}/cmake/pkg/${ProjectName}-config.cmake
+ ${PROJECT_BINARY_DIR}/${ProjectName}-config-version.cmake
+ DESTINATION ${DUNE_INSTALL_LIBDIR}/cmake/${ProjectName})
+
+ #install config.h
+ if(EXISTS ${CMAKE_SOURCE_DIR}/config.h.cmake)
+ install(FILES config.h.cmake DESTINATION share/${ProjectName})
+ endif(EXISTS ${CMAKE_SOURCE_DIR}/config.h.cmake)
+
+ #install pkg-config files
+ create_and_install_pkconfig(${DUNE_INSTALL_LIBDIR})
+
+ if("${ARGC}" EQUAL "1")
+ message(STATUS "Adding custom target for config.h generation")
+ dune_regenerate_config_cmake()
+ # add a target to generate config.h.cmake
+ add_custom_target(OUTPUT config.h.cmake
+ COMMAND dune_regenerate_config_cmake()
+ DEPENDS stamp-regenerate-config-h)
+ # actually write the config.h file to disk
+ # using generated file
+ configure_file(${CMAKE_CURRENT_BINARY_DIR}/config.h.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/config.h)
+ else("${ARGC}" EQUAL "1")
+ message(STATUS "Not adding custom target for config.h generation")
+ # actually write the config.h file to disk
+ configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
+ endif("${ARGC}" EQUAL "1")
+
+ test_dep()
+
+ include(CPack)
+
+ feature_summary(WHAT ALL)
+endmacro(finalize_dune_project)
+
+macro(target_link_dune_default_libraries _target)
+ foreach(_lib ${DUNE_DEFAULT_LIBS})
+ target_link_libraries(${_target} ${_lib})
+ endforeach(_lib ${DUNE_DEFAULT_LIBS})
+endmacro(target_link_dune_default_libraries)
+
+# Gets path to the common Dune CMake scripts
+macro(dune_common_script_dir _script_dir)
+ if("${CMAKE_PROJECT_NAME}" STREQUAL "dune-common")
+ set(${_script_dir} ${CMAKE_SOURCE_DIR}/cmake/scripts)
+ else("${CMAKE_PROJECT_NAME}" STREQUAL "dune-common")
+ set(${_script_dir} ${dune-common_SCRIPT_DIR})
+ endif("${CMAKE_PROJECT_NAME}" STREQUAL "dune-common")
+endmacro(dune_common_script_dir)
+
+# Gets path to the common Dune CMake scripts source
+macro(dune_common_script_source_dir _script_dir)
+ if("${CMAKE_PROJECT_NAME}" STREQUAL "dune-common")
+ set(${_script_dir} ${CMAKE_SOURCE_DIR}/cmake/scripts)
+ else("${CMAKE_PROJECT_NAME}" STREQUAL "dune-common")
+ set(${_script_dir} ${dune-ommon_SCRIPT_SOURCE_DIR})
+ endif("${CMAKE_PROJECT_NAME}" STREQUAL "dune-common")
+endmacro(dune_common_script_source_dir)
+
+function(dune_expand_object_libraries _SOURCES_var _ADD_LIBS_var _COMPILE_FLAGS_var)
+ set(_new_SOURCES "")
+ set(_new_ADD_LIBS "${${_ADD_LIBS_var}}")
+ set(_new_COMPILE_FLAGS "${${_COMPILE_FLAGS_var}}")
+ set(_regex "_DUNE_TARGET_OBJECTS:([a-zA-Z0-9_-]+)_")
+ foreach(_source ${${_SOURCES_var}})
+ string(REGEX MATCH ${_regex} _matched "${_source}")
+ if(_matched)
+ string(REGEX REPLACE "${_regex}" "\\1" _basename "${_source}")
+ foreach(var _SOURCES _ADD_LIBS _COMPILE_FLAGS)
+ get_property(_prop GLOBAL PROPERTY DUNE_LIB_${_basename}${var})
+ list(APPEND _new${var} "${_prop}")
+ endforeach(var _SOURCES _ADD_LIBS _COMPILE_FLAGS)
+ else(_matched)
+ list(APPEND _new_SOURCES "${_source}")
+ endif(_matched)
+ endforeach(_source ${${_SOURCES_var}})
+
+ foreach(var _SOURCES _ADD_LIBS _COMPILE_FLAGS)
+ set(${${var}_var} "${_new${var}}" PARENT_SCOPE)
+ endforeach(var _SOURCES _ADD_LIBS _COMPILE_FLAGS)
+endfunction(dune_expand_object_libraries)
+
+# Creates shared and static libraries with the same basename.
+# More docu can be found at the top of this file.
+macro(dune_add_library basename)
+ include(CMakeParseArguments)
+ cmake_parse_arguments(DUNE_LIB "NO_EXPORT;OBJECT" "COMPILE_FLAGS"
+ "ADD_LIBS;SOURCES" ${ARGN})
+ if(DUNE_LIB_OBJECT)
+ if(DUNE_LIB_${basename}_SOURCES)
+ message(FATAL_ERROR "There is already a library with the name ${basename}, "
+ "but only one is allowed!")
+ else(DUNE_LIB_${basename}_SOURCES)
+ foreach(source ${DUNE_LIB_UNPARSED_ARGUMENTS})
+ list(APPEND full_path_sources ${CMAKE_CURRENT_SOURCE_DIR}/${source})
+ endforeach(source ${DUNE_LIB_UNPARSED_ARGUMENTS})
+ # register sources, libs and flags for building the library later
+ define_property(GLOBAL PROPERTY DUNE_LIB_${basename}_SOURCES
+ BRIEF_DOCS "Convenience property with sources for library ${basename}. DO NOT EDIT!"
+ FULL_DOCS "Convenience property with sources for library ${basename}. DO NOT EDIT!")
+ set_property(GLOBAL PROPERTY DUNE_LIB_${basename}_SOURCES
+ "${full_path_sources}")
+ define_property(GLOBAL PROPERTY DUNE_LIB_${basename}_ADD_LIBS
+ BRIEF_DOCS "Convenience property with libraries for library ${basename}. DO NOT EDIT!"
+ FULL_DOCS "Convenience property with libraries for library ${basename}. DO NOT EDIT!")
+ set_property(GLOBAL PROPERTY DUNE_LIB_${basename}_ADD_LIBS
+ "${DUNE_LIB_ADD_LIBS}")
+ define_property(GLOBAL PROPERTY DUNE_LIB_${basename}_COMPILE_FLAGS
+ BRIEF_DOCS "Convenience property with compile flags for library ${basename}. DO NOT EDIT!"
+ FULL_DOCS "Convenience property with compile flags for library ${basename}. DO NOT EDIT!")
+ set_property(GLOBAL PROPERTY DUNE_LIB_${basename}_COMPILE_FLAGS
+ "${DUNE_LIB_COMPILE_FLAGS}")
+ endif(DUNE_LIB_${basename}_SOURCES)
+ else(DUNE_LIB_OBJECT)
+ list(APPEND DUNE_LIB_SOURCES ${DUNE_LIB_UNPARSED_ARGUMENTS})
+ dune_expand_object_libraries(DUNE_LIB_SOURCES DUNE_LIB_ADD_LIBS DUNE_LIB_COMPILE_FLAGS)
+ #create lib
+ add_library(${basename} ${DUNE_LIB_SOURCES})
+ get_property(_prop GLOBAL PROPERTY DUNE_MODULE_LIBRARIES)
+ set_property(GLOBAL PROPERTY DUNE_MODULE_LIBRARIES ${_prop} ${basename})
+ # link with specified libraries.
+ if(DUNE_LIB_ADD_LIBS)
+ dune_target_link_libraries(${basename} ${DUNE_LIB_ADD_LIBS})
+ endif(DUNE_LIB_ADD_LIBS)
+ if(DUNE_LIB_COMPILE_FLAGS)
+ setproperty(${basename} APPEND_STRING COMPILE_FLAGS
+ "${DUNE_LIB_COMPILE_FLAGS}")
+ endif(DUNE_LIB_COMPILE_FLAGS)
+ # Build library in ${PROJECT_BINARY_DIR}/lib
+ set_target_properties(${basename} PROPERTIES
+ LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib"
+ ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
+
+ set(_created_libs ${basename})
+
+ if(DUNE_BUILD_BOTH_LIBS)
+ if(BUILD_SHARED_LIBS)
+ #create static lib
+ add_library(${basename}-static STATIC ${DUNE_LIB_SOURCES})
+ # make sure both libs have the same name.
+ set_target_properties(${basename}-static PROPERTIES
+ OUTPUT_NAME ${basename}
+ ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
+ list(APPEND _created_libs ${basename}-static)
+ # link with specified libraries.
+ if(DUNE_LIB_ADD_LIBS)
+ dune_target_link_libraries(${basename}-static ${DUNE_LIB_ADD_LIBS})
+ endif(DUNE_LIB_ADD_LIBS)
+ if(DUNE_LIB_COMPILE_FLAGS)
+ setproperty(${basename}-static APPEND_STRING COMPILE_FLAGS
+ "${DUNE_LIB_COMPILE_FLAGS}")
+ endif(DUNE_LIB_COMPILE_FLAGS)
+ else(BUILD_SHARED_LIBS)
+ #create shared libs
+ add_library(${basename}-shared SHARED ${DUNE_LIB_SOURCES})
+ set_target_properties(${basename}-shared PROPERTIES
+ OUTPUT_NAME ${basename}
+ LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
+ # link with specified libraries.
+ if(DUNE_LIB_ADD_LIBS)
+ dune_target_link_libraries(${basename}-shared ${DUNE_LIB_ADD_LIBS})
+ endif(DUNE_LIB_ADD_LIBS)
+ if(DUNE_LIB_COMPILE_FLAGS)
+ setproperty(${basename}-shared APPEND_STRING COMPILE_FLAGS
+ "${DUNE_LIB_COMPILE_FLAGS}")
+ endif(DUNE_LIB_COMPILE_FLAGS)
+ list(APPEND _created_libs ${basename}-shared)
+ endif(BUILD_SHARED_LIBS)
+ endif(DUNE_BUILD_BOTH_LIBS)
+
+ if(NOT DUNE_LIB_NO_EXPORT)
+ if(NOT _MODULE_EXPORT_USED)
+ set(_MODULE_EXPORT_USED ON)
+ set(_append "")
+ else(NOT _MODULE_EXPORT_USED)
+ set(_append APPEND)
+ endif(NOT _MODULE_EXPORT_USED)
+ # install targets to use the libraries in other modules.
+ install(TARGETS ${_created_libs}
+ EXPORT ${ProjectName}-targets DESTINATION ${CMAKE_INSTALL_LIBDIR})
+ install(EXPORT ${ProjectName}-targets
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${ProjectName})
+
+ # export libraries for use in build tree
+ export(TARGETS ${_created_libs} ${_append}
+ FILE ${PROJECT_BINARY_DIR}/${ProjectName}-targets.cmake)
+ endif(NOT DUNE_LIB_NO_EXPORT)
+ endif(DUNE_LIB_OBJECT)
+endmacro(dune_add_library basename sources)
+
+macro(replace_properties_for_one)
+ get_property(properties ${option_command} ${_target}
+ PROPERTY ${REPLACE_PROPERTY})
+ if(NOT properties)
+ # property not set. set it directly
+ foreach(i RANGE 0 ${hlength})
+ math(EXPR idx "(2 * ${i}) + 1")
+ list(GET REPLACE_UNPARSED_ARGUMENTS ${idx} repl)
+ list(APPEND replacement ${repl})
+ endforeach(i RANGE 0 ${hlength})
+ list(REMOVE_DUPLICATES replacement)
+ set_property(${option_command} ${_target} ${REPLACE_APPEND}
+ ${REPLACE_APPEND_STRING} PROPERTY ${REPLACE_PROPERTY} ${replacement})
+ else(NOT properties)
+ foreach(prop ${properties})
+ set(matched FALSE)
+ foreach(i RANGE 0 ${hlength})
+ math(EXPR regexi "2 * ${i}")
+ math(EXPR repli "${regexi} +1")
+ list(GET REPLACE_UNPARSED_ARGUMENTS ${regexi} regex)
+ list(GET REPLACE_UNPARSED_ARGUMENTS ${repli} replacement)
+ string(REGEX MATCH ${regex} match ${prop})
+
+ if(match)
+ list(APPEND new_props ${replacement})
+ set(matched TRUE)
+ endif(match)
+ endforeach(i RANGE 0 ${hlength})
+
+ if(NOT matched)
+ list(APPEND new_props ${prop})
+ endif(NOT matched)
+ endforeach(prop ${properties})
+ list(REMOVE_DUPLICATES new_props)
+ set_property(${option_command} ${_target}
+ PROPERTY ${REPLACE_PROPERTY} ${new_props})
+ endif(NOT properties)
+ get_property(properties ${option_command} ${_target} PROPERTY ${REPLACE_PROPERTY})
+endmacro(replace_properties_for_one)
+
+function(dune_target_link_libraries basename libraries)
+ target_link_libraries(${basename} ${libraries})
+ if(DUNE_BUILD_BOTH_LIBS)
+ if(BUILD_SHARED_LIBS)
+ target_link_libraries(${basename}-static ${libraries})
+ else(BUILD_SHARED_LIBS)
+ target_link_libraries(${basename}-shared ${libraries})
+ endif(BUILD_SHARED_LIBS)
+ endif(DUNE_BUILD_BOTH_LIBS)
+endfunction(dune_target_link_libraries basename libraries)
+
+function(replace_properties)
+ include(CMakeParseArguments)
+ set(_first_opts "GLOBAL;DIRECTORY;TARGET;SOURCE;CACHE")
+ cmake_parse_arguments(REPLACE "GLOBAL"
+ "DIRECTORY;PROPERTY" "TARGET;SOURCE;TEST;CACHE" ${ARGN})
+
+ set(MY_DIRECTORY TRUE)
+ foreach(i ${_first_opts})
+ if(REPLACE_${i})
+ set(MY_DIRECTORY FALSE)
+ endif(REPLACE_${i})
+ endforeach(i ${_first_opts})
+ if(NOT MY_DIRECTORY)
+ list(FIND REPLACE_UNPARSED_ARGUMENTS DIRECTORY _found)
+ if(_found GREATER -1)
+ list(REMOVE_AT REPLACE_UNPARSED_ARGUMENTS ${_found})
+ set(MY_DIRECTORY TRUE)
+ set(REPLACE_DIRECTORY "")
+ endif(_found GREATER -1)
+ else(NOT MY_DIRECTORY)
+ #set(REPLACE_PROPERTY
+ endif(NOT MY_DIRECTORY)
+
+ #setup options
+ if(REPLACE_GLOBAL)
+ set(option_command GLOBAL)
+ elseif(MY_DIRECTORY)
+ set(option_command DIRECTORY)
+ elseif(REPLACE_DIRECTORY)
+ set(option_command DIRECTORY)
+ set(option_arg ${REPLACE_DIRECTORY})
+ elseif(REPLACE_TARGET)
+ set(option_command TARGET)
+ set(option_arg ${REPLACE_TARGET})
+ elseif(REPLACE_SOURCE)
+ set(option_command SOURCE)
+ set(option_arg ${REPLACE_SOURCE})
+ elseif(REPLACE_TEST)
+ set(option_command TEST)
+ set(option_arg${REPLACE_TEST})
+ elseif(REPLACE_CACHE)
+ set(option_command CACHE)
+ set(option_arg ${REPLACE_CACHE})
+ endif()
+
+ if(NOT (REPLACE_CACHE OR REPLACE_TEST OR REPLACE_SOURCE
+ OR REPLACE_TARGET OR REPLACE_DIRECTORY OR REPLACE_GLOBAL
+ OR MY_DIRECTORY))
+ message(ERROR "One of GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, or CACHE"
+ " has to be present")
+ endif()
+
+ list(LENGTH REPLACE_UNPARSED_ARGUMENTS length)
+# if(NOT (REPLACE_GLOBAL AND REPLACE_TARGET AND
+# REPLACE_SOURCE AND REPLACE
+ math(EXPR mlength "${length} % 2 ")
+ math(EXPR hlength "${length} / 2 - 1")
+
+ if(NOT ${mlength} EQUAL 0)
+ message(ERROR "You need to specify pairs consisting of a regular expression and a replacement string.")
+ endif(NOT ${mlength} EQUAL 0)
+
+ if(NOT length GREATER 0)
+ message(ERROR "You need to specify at least on pair consisting of a regular expression
+and a replacement string. ${REPLACE_UNPARSED_ARGUMENTS}")
+ endif(NOT length GREATER 0)
+
+ foreach(_target ${option_arg})
+ replace_properties_for_one()
+ endforeach(_target ${option_arg})
+
+ list(LENGTH option_arg _length)
+ if(_length EQUAL 0)
+ replace_properties_for_one()
+ endif(_length EQUAL 0)
+endfunction(replace_properties)
+
+macro(add_dune_all_flags targets)
+ get_property(flags GLOBAL PROPERTY ALL_PKG_FLAGS)
+ set(FLAGSTR "")
+ foreach(flag ${flags})
+ set(FLAGSTR "${FLAGSTR}\ ${flag}")
+ endforeach()
+ foreach(target ${targets})
+ set_property(TARGET ${target}
+ APPEND_STRING
+ PROPERTY COMPILE_FLAGS ${FLAGSTR})
+ endforeach()
+endmacro(add_dune_all_flags targets)
--- /dev/null
+# searches for pkg-config, creates the
+# file <module-name>.pc from <module-name>.pc.in,
+# and adds installation directives.
+#
+
+find_package(PkgConfig)
+
+function(create_and_install_pkconfig installlibdir)
+ # set some variables that are used in the pkg-config file
+ include(GNUInstallDirs)
+ set( prefix ${CMAKE_INSTALL_PREFIX})
+ set(exec_prefix "\${prefix}")
+ set(libdir "\${exec_prefix}/${installlibdir}")
+ set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
+ set(PACKAGE_NAME ${ProjectName})
+ set(VERSION ${ProjectVersion})
+ set(CC ${CMAKE_C_COMPILER})
+ set(CXX "${CMAKE_CXX_COMPILER} ${CXX_STD11_FLAGS}")
+
+ if(DUNE_DEPENDS)
+ foreach(_DUNE_DEPEND ${DUNE_DEPENDS})
+ string(REGEX REPLACE "\\(" "" REQF1 ${_DUNE_DEPEND})
+ string(REGEX REPLACE "\\)" "" LR ${REQF1})
+ if(REQUIRES)
+ set(REQUIRES "${REQUIRES} ${LR}")
+ else()
+ set(REQUIRES ${LR})
+ endif(REQUIRES)
+ endforeach(_DUNE_DEPEND ${DUNE_DEPENDS})
+ endif(DUNE_DEPENDS)
+
+ #create pkg-config file
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/${ProjectName}.pc.in
+ ${PROJECT_BINARY_DIR}/${ProjectName}.pc
+ @ONLY
+ )
+
+ # install pkgconfig file
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${ProjectName}.pc
+ DESTINATION ${installlibdir}/pkgconfig)
+
+endfunction(create_and_install_pkconfig)
--- /dev/null
+# Module configures the DUNE debug streams.
+# A default debug level can be specified with
+# MINIMAL_DEBUG_LEVEL
+#
+macro(dune_set_minimal_debug_level)
+set(MINIMAL_DEBUG_LEVEL ON CACHE STRING "set the MINIMAL_DEBUG_LEVEL. Standard debug streams with level below MINIMAL_DEBUG_LEVEL will collapse to doing nothing if output is requested. (default=warn)")
+set_property(CACHE MINIMAL_DEBUG_LEVEL PROPERTY STRINGS
+ "grave" "warn" "info" "verb" "vverb")
+if(MINIMAL_DEBUG_LEVEL MATCHES "grave")
+ set(DUNE_MINIMAL_DEBUG_LEVEL 5)
+elseif(MINIMAL_DEBUG_LEVEL MATCHES "info")
+ set(DUNE_MINIMAL_DEBUG_LEVEL 3)
+elseif(MINIMAL_DEBUG_LEVEL MATCHES "verb")
+ set(DUNE_MINIMAL_DEBUG_LEVEL 2)
+elseif(MINIMAL_DEBUG_LEVEL MATCHES "vverb")
+ set(DUNE_MINIMAL_DEBUG_LEVEL 1)
+else()
+ set(DUNE_MINIMAL_DEBUG_LEVEL 4)
+endif()
+endmacro(dune_set_minimal_debug_level)
--- /dev/null
+# Module provides macros that allow for on demand test building.
+# In DUNE tests are not built by make all but by make test.
+#
+# Provides the following macros:
+#
+# test_dep()
+#
+# Finds all directories called test and creates a dependency for
+# testing that calls builds the tests for this directory.
+#
+#
+# add_directory_test_target(_target)
+#
+# Creates a custom target for building
+# the tests in the current directory.
+#
+# The target name will be the path of the
+# current directory relative to ${CMAKE_BINARY_DIR}
+# with all slashes replaced by underlines.
+# E.g. for dune/istl/test the target will be dune_istl_test.
+#
+macro(test_dep)
+ dune_common_script_dir(SCRIPT_DIR)
+ get_filename_component(RELPATH "${CMAKE_SOURCE_DIR}" REALPATH)
+ execute_process(COMMAND ${CMAKE_COMMAND} -D RELPATH=${RELPATH} -P ${SCRIPT_DIR}/FindFiles.cmake
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ RESULT_VARIABLE _res ERROR_VARIABLE _dirs)
+
+ foreach(_dir ${_dirs})
+ string(REGEX REPLACE "([^ \t\n]+)[ \n\t]*$" "\\1" _dir ${_dir})
+ set_property(DIRECTORY ${_dir} PROPERTY TEST_INCLUDE_FILE ${CMAKE_BINARY_DIR}/${_dir}/BuildTests.cmake)
+ endforeach(_dir ${_dirs})
+endmacro(test_dep)
+
+macro(get_directory_test_target _target _dir)
+ string(REPLACE "${CMAKE_BINARY_DIR}" "" _relative_dir "${_dir}")
+ string(REPLACE "/" "_" ${_target} "${_relative_dir}")
+endmacro(get_directory_test_target _target _dir)
+
+#
+# - Create a custom target for building
+# the tests in the current directory.
+#
+# The target name will be the path of the
+# current directory relative to ${CMAKE_BINARY_DIR}
+# with all slashes replaced by underlines.
+# E.g. for dune/istl/test the target will be dune_istl_test.
+#
+macro(add_directory_test_target _target)
+ get_directory_test_target(${_target} "${CMAKE_CURRENT_BINARY_DIR}")
+ add_custom_target(${${_target}})
+ dune_common_script_dir(SCRIPT_DIR)
+ configure_file(${SCRIPT_DIR}/BuildTests.cmake.in BuildTests.cmake @ONLY)
+endmacro(add_directory_test_target)
--- /dev/null
+# Create a custom target for building the tests.
+# Thus they will not be built by make all any more.
+# Actually I wanted this target to be a dependency
+# of make test but that is currently not possible.
+# See http://public.kitware.com/Bug/view.php?id=8438
+# This really sucks!
+# Therefore currently make build_tests has to be called
+# before make test.
+
+# enable testing before adding the subdirectories.
+# Thus we can add the tests in the subdirectories
+# where they actually are.
+enable_testing()
+
+#activate CTest
+include(CTest)
+
+#include our macros
+include(DuneTestMacros)
--- /dev/null
+#
+# Module that checks whether boost::fusion is available and usable.
+#
+# Sets the follwing variable:
+#
+# HAVE_BOOST_FUSION True if boost::fusion is available.
+#
+include(DuneBoost)
+
+if(BOOST_FOUND)
+ message(STATUS "Checking whether the Boost::FUSION library is available.")
+ check_cxx_source_compiles("
+\#include <boost/fusion/container.hpp>
+int main(){
+ boost::fusion::vector<int,char,double> v;
+ return 0;
+}" HAVE_BOOST_FUSION )
+ if(HAVE_BOOST_FUSION)
+ message(STATUS "Boost::FUSION is available")
+ endif(HAVE_BOOST_FUSION)
+else(BOOST_FOUND)
+ message(STATUS "Skipping check for Boost::FUSION as Boost is not available.")
+endif(BOOST_FOUND)
--- /dev/null
+# Module that checks for the GNU MP Bignum (GMP) library, include
+# dirs and
+#
+# Variables used by this module which you may want to set:
+# GMP_ROOT Path list to search for GMP
+#
+# Sets the following variables:
+# GMP_FOUND True if the GMP library was found.
+#
+
+# search for location of header gmpxx.h", only at positions given by the user
+find_path(GMP_INCLUDE_DIR
+ NAMES "gmpxx.h"
+ PATHS ${GMP_PREFIX} ${GMP_ROOT}
+ PATH_SUFFIXES include
+ NO_DEFAULT_PATH)
+# try default paths now
+find_path(GMP_INCLUDE_DIR
+ NAMES "gmpxx.h")
+
+# check if header is accepted
+include(CMakePushCheckState)
+cmake_push_check_state()
+set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${GMP_INCLUDE_DIR})
+include(CheckIncludeFileCXX)
+check_include_file_cxx("gmpxx.h" GMP_HEADER_WORKS)
+
+# look for library gmp, only at positions given by the user
+find_library(GMP_LIB gmp
+ PATHS ${GMP_PREFIX} ${GMP_ROOT}
+ PATH_SUFFIXES lib lib64
+ NO_DEFAULT_PATH
+ DOC "GNU GMP library")
+# try default paths now
+find_library(GMP_LIB gmp)
+
+# look for library gmpxx, only at positions given by the user
+find_library(GMPXX_LIB gmpxx
+ PATHS ${GMP_PREFIX} ${GMP_ROOT}
+ PATH_SUFFIXES lib lib64
+ NO_DEFAULT_PATH
+ DOC "GNU GMPXX library")
+# try default paths now
+find_library(GMPXX_LIB gmpxx)
+
+# check if library works
+if(GMP_LIB AND GMPXX_LIB)
+ include(CheckSymbolExists)
+ check_library_exists(${GMP_LIB} __gmpz_abs "" GMPXX_LIB_WORKS)
+endif(GMP_LIB AND GMPXX_LIB)
+cmake_pop_check_state()
+
+# behave like a CMake module is supposed to behave
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(
+ "GMP"
+ DEFAULT_MSG
+ GMP_INCLUDE_DIR GMP_LIB GMPXX_LIB GMP_HEADER_WORKS GMPXX_LIB_WORKS
+)
+
+mark_as_advanced(GMP_LIB GMPXX_LIB GMP_INCLUDE_DIR)
+
+# if both headers and library are found, store results
+if(GMP_FOUND)
+ set(GMP_INCLUDE_DIRS ${GMP_INCLUDE_DIR})
+ set(GMP_LIBRARIES ${GMP_LIB} ${GMPXX_LIB})
+ set(GMP_COMPILE_FLAGS "-DENABLE_GMP=1")
+ # log result
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Determing location of GMP succeded:\n"
+ "Include directory: ${GMP_INCLUDE_DIRS}\n"
+ "Library directory: ${GMP_LIBRARIES}\n\n")
+else(GMP_FOUND)
+ # log errornous result
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Determing location of GMP failed:\n"
+ "Include directory: ${GMP_INCLUDE_DIR}\n"
+ "gmp library directory: ${GMP_LIB}\n"
+ "gmpx library directory: ${GMPXX_LIB}\n\n")
+endif(GMP_FOUND)
+
+# set HAVE_GMP for config.h
+set(HAVE_GMP ${GMP_FOUND})
+
+#add all GMP related flags to ALL_PKG_FLAGS, this must happen regardless of a target using add_dune_gmp_flags
+if(HAVE_GMP)
+ set_property(GLOBAL APPEND PROPERTY ALL_PKG_FLAGS "-DENABLE_GMP=1")
+ foreach(dir ${GMP_INCLUDE_DIR})
+ set_property(GLOBAL APPEND PROPERTY ALL_PKG_FLAGS "-I${dir}")
+ endforeach()
+endif()
--- /dev/null
+# Module that checks for inkscape
+#
+# Sets the following variables
+#
+# INSCAPE: Path to inkscape to generate .png's form .svg's
+#
+# Provides the following functions:
+#
+# inkscape_generate_png_from_svg([OUTPUT_DIR <output_dir>] <pngfile1.png> [<pngfile2.png> ....])
+#
+# Generates pngfile1, ... from svg input files pngfile1.svg, ....
+# The output directory can be specified with the option OUTPUT_DIR. If it is omitted
+# the files will be generated in CMAKE_CURRENT_BINARY_DIR.
+
+find_program(INKSCAPE inkscape DOC "Path to inkscape to generate png files from svg files")
+find_program(CONVERT convert DOC "Path to convert program")
+if(INKSCAPE)
+ set(INKSCAPE_FOUND True)
+endif(INKSCAPE)
+
--- /dev/null
+# Accepts the following variables:
+#
+# METIS_ROOT: Prefix where METIS is installed.
+# METIS_LIB_NAME: Name of the METIS library (default: metis).
+# METIS_LIBRARY: Full path of the METIS library.
+
+# Sets the following variables:
+#
+# METIS_LIBRARY: Full path of the METIS library.
+# METIS_FOUND: True if ParMETIS was found.
+# METIS_LIBRARIES: List of all libraries needed for linking with METIS,
+#
+# Provides the following macros:
+#
+# find_package(METIS)
+#
+# Searches for METIS (See above)
+
+
+# search metis header
+find_path(METIS_INCLUDE_DIR metis.h
+ PATHS ${METIS_DIR} ${METIS_ROOT}
+ PATH_SUFFIXES metis include include/metis Lib METISLib
+ NO_DEFAULT_PATH
+ DOC "Include directory of metis")
+find_path(METIS_INCLUDE_DIR metis.h
+ PATH_SUFFIXES metis include include/metis Lib METISLib)
+
+set(METIS_LIBRARY METIS_LIBRARY-NOTFOUND CACHE FILEPATH "Full path of the METIS library")
+
+# check metis header
+include(CMakePushCheckState)
+cmake_push_check_state() # Save variables
+set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${METIS_INCLUDE_DIR})
+check_include_file(metis.h METIS_FOUND)
+
+# search metis library
+if(NOT METIS_LIB_NAME)
+ set(METIS_LIB_NAME metis)
+endif(NOT METIS_LIB_NAME)
+
+find_library(METIS_LIBRARY ${METIS_LIB_NAME}
+ PATHS ${METIS_DIR} ${METIS_ROOT}
+ PATH_SUFFIXES lib
+ NO_DEFAULT_PATH)
+find_library(METIS_LIBRARY ${METIS_LIB_NAME}
+ PATH_SUFFIXES lib
+)
+
+# check metis library
+if(METIS_LIBRARY)
+ list(APPEND CMAKE_REQUIRED_LIBRARIES ${METIS_LIBRARIY})
+ set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${METIS_LIBRARY})
+ include(CheckSymbolExists)
+ check_function_exists(METIS_PartGraphKway HAVE_METIS_PARTGRAPHKWAY)
+endif(METIS_LIBRARY)
+
+# behave like a CMake module is supposed to behave
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(
+ "METIS"
+ DEFAULT_MSG
+ METIS_INCLUDE_DIR
+ METIS_LIBRARY
+ HAVE_METIS_PARTGRAPHKWAY
+)
+
+cmake_pop_check_state()
+
+mark_as_advanced(METIS_INCLUDE_DIR METIS_LIBRARIES METIS_LIB_NAME)
+
+# if both headers and library are found, store results
+if(METIS_FOUND)
+ set(METIS_INCLUDE_DIRS ${METIS_INCLUDE_DIR})
+ set(METIS_LIBRARIES ${METIS_LIBRARY})
+ set(HAVE_METIS ${METIS_FOUND})
+ # log result
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Determing location of METIS succeded:\n"
+ "Include directory: ${METIS_INCLUDE_DIRS}\n"
+ "Library directory: ${METIS_LIBRARIES}\n\n")
+else(METIS_FOUND)
+ # log errornous result
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Determing location of METIS failed:\n"
+ "Include directory: ${METIS_INCLUDE_DIRS}\n"
+ "Library directory: ${METIS_LIBRARIES}\n\n")
+endif(METIS_FOUND)
+
+#add all metis related flags to ALL_PKG_FLAGS, this must happen regardless of a target using add_dune_metis_flags
+if(METIS_FOUND)
+ foreach(dir ${METIS_INCLUDE_DIRS})
+ set_property(GLOBAL APPEND PROPERTY ALL_PKG_FLAGS "-I${dir}")
+ endforeach()
+endif()
--- /dev/null
+#
+# Module that detects mproctect support
+#
+# Sets the following variables
+# HAVE_SYS_MMAN_H
+# HAVE_MPROTECT
+check_include_file("sys/mman.h" HAVE_SYS_MMAN_H)
+include(CheckCSourceCompiles)
+check_c_source_compiles("
+#include <sys/mman.h>
+int main(void){
+ mprotect(0,0,PROT_NONE);
+}" HAVE_MPROTECT)
--- /dev/null
+# Module that checks whether ParMETIS is available.
+#
+# Accepts the following variables:
+#
+# PARMETIS_ROOT: Prefix where ParMETIS is installed.
+# METIS_LIB_NAME: Name of the METIS library (default: metis).
+# PARMETIS_LIB_NAME: Name of the ParMETIS library (default: parmetis).
+# METIS_LIBRARY: Full path of the METIS library.
+# PARMETIS_LIBRARY: Full path of the ParMETIS library
+
+# Sets the following variables:
+#
+# METIS_LIBRARY: Full path of the METIS library.
+# PARMETIS_LIBRARY: Full path of the ParMETIS library.
+# PARMETIS_FOUND: True if ParMETIS was found.
+# PARMETIS_LIBRARIES: List of all libraries needed for linking with ParMETIS,
+#
+# Provides the following macros:
+#
+# find_package(ParMETIS)
+
+find_path(PARMETIS_INCLUDE_DIR parmetis.h
+ PATHS ${PARMETIS_DIR} ${PARMETIS_ROOT}
+ PATH_SUFFIXES include parmetis
+ NO_DEFAULT_PATH
+ DOC "Include directory of ParMETIS")
+find_path(PARMETIS_INCLUDE_DIR parmetis.h
+ PATH_SUFFIXES include parmetis)
+
+set(METIS_LIB_NAME metis
+ CACHE STRING "Name of the METIS library (default: metis).")
+set(PARMETIS_LIB_NAME parmetis
+ CACHE STRING "Name of the ParMETIS library (default: parmetis).")
+set(METIS_LIBRARY METIS_LIBRARY-NOTFOUND
+ CACHE FILEPATH "Full path of the METIS library")
+set(PARMETIS_LIBRARY ParMETIS_LIBRARY-NOTFOUND
+ CACHE FILEPATH "Full path of the ParMETIS library")
+
+# check METIS and ParMETIS headers
+include(CMakePushCheckState)
+cmake_push_check_state() # Save variables
+set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${MPI_DUNE_INCLUDE_PATH} ${PARMETIS_INCLUDE_DIR})
+set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${MPI_DUNE_COMPILE_FLAGS}")
+check_include_file(metis.h METIS_FOUND)
+check_include_file(parmetis.h PARMETIS_FOUND)
+
+if(PARMETIS_FOUND)
+ set(ParMETIS_INCLUDE_PATH ${CMAKE_REQUIRED_INCLUDES})
+ set(ParMETIS_COMPILE_FLAGS "${CMAKE_REQUIRED_FLAGS} -DENABLE_PARMETIS=1")
+
+ # search METIS library
+ find_library(METIS_LIBRARY metis
+ PATHS ${PARMETIS_DIR} ${PARMETIS_ROOT}
+ PATH_SUFFIXES lib
+ NO_DEFAULT_PATH)
+ find_library(METIS_LIBRARY metis)
+
+ # search ParMETIS library
+ find_library(PARMETIS_LIBRARY parmetis
+ PATHS ${PARMETIS_DIR} ${PARMETIS_ROOT}
+ PATH_SUFFIXES lib
+ NO_DEFAULT_PATH)
+ find_library(PARMETIS_LIBRARY parmetis)
+
+ # check ParMETIS library
+ if(PARMETIS_LIBRARY)
+ list(APPEND CMAKE_REQUIRED_LIBRARIES ${PARMETIS_LIBRARY} ${METIS_LIBRARY} ${MPI_DUNE_LIBRARIES})
+ include(CheckFunctionExists)
+ check_function_exists(parmetis_v3_partkway HAVE_PARMETIS)
+ endif(PARMETIS_LIBRARY)
+endif(PARMETIS_FOUND)
+
+# behave like a CMake module is supposed to behave
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(
+ "ParMETIS"
+ DEFAULT_MSG
+ PARMETIS_INCLUDE_DIR
+ PARMETIS_LIBRARY
+ HAVE_PARMETIS
+)
+
+mark_as_advanced(PARMETIS_INCLUDE_DIR METIS_LIBRARY PARMETIS_LIBRARY METIS_LIB_NAME PARMETIS_LIB_NAME)
+
+#restore old values
+cmake_pop_check_state()
+
+if(PARMETIS_FOUND)
+ set(PARMETIS_INCLUDE_DIRS ${PARMETIS_INCLUDE_DIR})
+ set(PARMETIS_LIBRARIES "${PARMETIS_LIBRARY};${METIS_LIBRARY};${MPI_DUNE_LIBRARIES}"
+ CACHE FILEPATH "ParMETIS libraries needed for linking")
+ set(PARMETIS_LINK_FLAGS "${DUNE_MPI_LINK_FLAGS}"
+ CACHE STRING "ParMETIS link flags")
+ # log result
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Determing location of ParMETIS succeded:\n"
+ "Include directory: ${PARMETIS_INCLUDE_DIRS}\n"
+ "Library directory: ${PARMETIS_LIBRARIES}\n\n")
+endif(PARMETIS_FOUND)
+
+#add all parmetis related flags to ALL_PKG_FLAGS, this must happen regardless of a target using add_dune_parmetis_flags
+if(PARMETIS_FOUND)
+ foreach(dir ${PARMETIS_INCLUDE_DIRS})
+ set_property(GLOBAL APPEND PROPERTY ALL_PKG_FLAGS "-I${dir}")
+ endforeach()
+endif()
\ No newline at end of file
--- /dev/null
+# Module that checks whether UMFPack is available.
+#
+# Variables used by this module which you may want to set:
+# UMFPACK_ROOT Path list to search for UMFPack
+#
+# Sets the following variables
+#
+# UMFPACK_FOUND True if UMFPack was found and usable
+# UMFPACK_INCLUDE_DIRS Path to the UMFPack include dirs
+# UMFPACK_LIBRARIES Name of the UMFPack libraries
+#
+
+find_package(BLAS QUIET REQUIRED)
+if(NOT BLAS_FOUND)
+ message(WARNING "UMFPack requires BLAS which was not found, skipping the test.")
+ return()
+endif()
+
+find_library(AMD_LIBRARY
+ NAMES "amd"
+ PATHS ${UMFPACK_ROOT}
+ PATH_SUFFIXES "lib" "lib32" "lib64" "AMD" "AMD/Lib"
+ NO_DEFAULT_PATH
+)
+
+find_library(AMD_LIBRARY
+ NAMES "amd"
+ PATH_SUFFIXES "lib" "lib32" "lib64" "AMD" "AMD/Lib"
+)
+
+if(NOT AMD_LIBRARY)
+ message(WARNING "UMFPack requires AMD (approximate minimum degree ordering) which was not found, skipping the test.")
+ return()
+endif()
+
+#look for header files at positions given by the user
+find_path(UMFPACK_INCLUDE_DIR
+ NAMES "umfpack.h"
+ PATHS ${UMFPACK_ROOT}
+ PATH_SUFFIXES "umfpack" "include/umfpack" "suitesparse" "include" "src" "UMFPACK" "UMFPACK/Include"
+ NO_DEFAULT_PATH
+)
+#now also look for default paths
+find_path(UMFPACK_INCLUDE_DIR
+ NAMES "umfpack.h"
+ PATH_SUFFIXES "umfpack" "include/umfpack" "suitesparse" "include" "UMFPACK" "UMFPACK/Include"
+)
+
+#look for library at positions given by the user
+find_library(UMFPACK_LIBRARY
+ NAMES "umfpack"
+ PATHS ${UMFPACK_ROOT}
+ PATH_SUFFIXES "lib" "lib32" "lib64" "UMFPACK" "UMFPACK/Lib"
+ NO_DEFAULT_PATH
+)
+#now also include the deafult paths
+find_library(UMFPACK_LIBRARY
+ NAMES "umfpack"
+ PATH_SUFFIXES "lib" "lib32" "lib64" "UMFPACK" "UMFPACK/Lib"
+)
+
+# behave like a CMake module is supposed to behave
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(
+ "UMFPack"
+ DEFAULT_MSG
+ UMFPACK_INCLUDE_DIR
+ UMFPACK_LIBRARY
+)
+
+mark_as_advanced(UMFPACK_INCLUDE_DIR UMFPACK_LIBRARY)
+
+# if both headers and library are found, store results
+if(UMFPACK_FOUND)
+ set(UMFPACK_INCLUDE_DIRS ${UMFPACK_INCLUDE_DIR})
+ set(UMFPACK_LIBRARIES ${UMFPACK_LIBRARY})
+ # log result
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Determining location of UMFPack succeded:\n"
+ "Include directory: ${UMFPACK_INCLUDE_DIRS}\n"
+ "Library directory: ${UMFPACK_LIBRARIES}\n\n")
+ set(UMFPACK_DUNE_COMPILE_FLAGS "-I${UMFPACK_INCLUDE_DIRS}"
+ CACHE STRING "Compile Flags used by DUNE when compiling with UMFPack programs")
+ set(UMFPACK_DUNE_LIBRARIES ${UMFPACK_LIBRARIES} ${BLAS_LIBRARIES} ${AMD_LIBRARY}
+ CACHE STRING "Libraries used by DUNE when linking UMFPack programs")
+else(UMFPACK_FOUND)
+ # log errornous result
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKES_FILES_DIRECTORY}/CMakeError.log
+ "Determing location of UMFPack failed:\n"
+ "Include directory: ${UMFPACK_INCLUDE_DIRS}\n"
+ "Library directory: ${UMFPACK_LIBRARIES}\n\n")
+endif(UMFPACK_FOUND)
+
+#set HAVE_UMFPACK for config.h
+set(HAVE_UMFPACK ${UMFPACK_FOUND})
+
+#add all umfpack related flags to ALL_PKG_FLAGS, this must happen regardless of a target using add_dune_umfpack_flags
+if(UMFPACK_FOUND)
+ set_property(GLOBAL APPEND PROPERTY ALL_PKG_FLAGS "${UMFPACK_DUNE_COMPILE_FLAGS}")
+ foreach(dir "${UMFPACK_INCLUDE_DIRS}")
+ set_property(GLOBAL APPEND PROPERTY ALL_PKG_FLAGS "-I${dir}")
+ endforeach()
+endif()
--- /dev/null
+# sets up a global property with the names of all header files
+# in the module and a global target depending on all checks
+macro(setup_headercheck)
+ #glob for headers
+ file(GLOB_RECURSE src_headers "src/*.hh")
+ file(GLOB_RECURSE dune_headers "dune/*.hh")
+ # strip hidden files
+ string(REGEX REPLACE "[^;]*/\\.[^;]*\\.hh;?" "" headers "${dune_headers};${src_headers}")
+ set_property(GLOBAL PROPERTY headercheck_list ${headers})
+
+ #define headercheck target
+ dune_common_script_dir(SCRIPT_DIR)
+ add_custom_target(headercheck ${CMAKE_COMMAND} -P ${SCRIPT_DIR}/FinalizeHeadercheck.cmake
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
+endmacro(setup_headercheck)
+
+# these macros are used to exclude headers from make headercheck
+# call this from a CMakeLists.txt file with a list of headers in that directory
+macro(exclude_from_headercheck)
+ #make this robust to argument being passed with or without ""
+ string(REGEX REPLACE "[\ \n]+([^\ ])" ";\\1" list ${ARGV0})
+ set(list "${list};${ARGV}")
+ get_property(headerlist GLOBAL PROPERTY headercheck_list)
+ foreach(item ${list})
+ list(REMOVE_ITEM headerlist "${CMAKE_CURRENT_SOURCE_DIR}/${item}")
+ endforeach()
+ set_property(GLOBAL PROPERTY headercheck_list ${headerlist})
+endmacro(exclude_from_headercheck)
+
+macro(exclude_dir_from_headercheck)
+ file(GLOB list RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.hh")
+ exclude_from_headercheck(${list})
+endmacro(exclude_dir_from_headercheck)
+
+macro(exclude_all_but_from_headercheck)
+ file(GLOB excllist RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.hh")
+ #make this robust to argument being passed with or without ""
+ string(REGEX REPLACE "[\ \n]+([^\ \n])" ";\\1" list ${ARGV0})
+ set(list "${list};${ARGV}")
+ foreach(item ${list})
+ list(REMOVE_ITEM excllist ${item})
+ endforeach()
+ exclude_from_headercheck(${excllist})
+endmacro(exclude_all_but_from_headercheck)
+
+# configure all headerchecks
+macro(finalize_headercheck)
+ get_property(headerlist GLOBAL PROPERTY headercheck_list)
+ foreach(header ${headerlist})
+ #do some name conversion
+ string(REGEX REPLACE ".*/([^/]*)" "\\1" simple ${header})
+ string(REPLACE ${PROJECT_SOURCE_DIR} "" rel ${header})
+ string(REGEX REPLACE "(.*)/[^/]*" "\\1" relpath ${rel})
+ string(REGEX REPLACE "/" "_" targname ${rel})
+
+ #generate the headercheck .cc file
+ file(WRITE ${CMAKE_BINARY_DIR}/headercheck/${rel}.cc "#ifdef HAVE_CONFIG_H\n#include<config.h>\n#endif\n#include<${simple}>\n#include<${simple}>\nint main(){return 0;}")
+
+ # add target for the check of current header, this is implemented as a library
+ # to prevent CMake from automatically trying to link the target, functionality
+ # of macro try_compile() is unfortunately not availbale due to it not being scriptable.
+ add_library(headercheck_${targname} STATIC EXCLUDE_FROM_ALL
+ ${CMAKE_BINARY_DIR}/headercheck/${rel}.cc)
+ add_dependencies(headercheck headercheck_${targname})
+
+ #add PKG_ALL_FLAGS and the directory where the header is located
+ set_property(TARGET headercheck_${targname}
+ APPEND_STRING PROPERTY COMPILE_FLAGS "-DHEADERCHECK -I${PROJECT_SOURCE_DIR}${relpath} -I${CMAKE_BINARY_DIR}")
+ set_property(TARGET headercheck_${targname} PROPERTY ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/headercheck/${relpath}")
+ add_dune_all_flags(headercheck_${targname})
+ unset(headercheck_${targname}_LIB_DEPENDS CACHE)
+ endforeach(header ${headerlist})
+endmacro(finalize_headercheck)
--- /dev/null
+# cmake/modules/language_support.cmake
+#
+# Temporary additional general language support is contained within this
+# file.
+
+# This additional function definition is needed to provide a workaround for
+# CMake bug 9220.
+
+# On debian testing (cmake 2.6.2), I get return code zero when calling
+# cmake the first time, but cmake crashes when running a second time
+# as follows:
+#
+# -- The Fortran compiler identification is unknown
+# CMake Error at /usr/share/cmake-2.6/Modules/CMakeFortranInformation.cmake:7 (GET_FILENAME_COMPONENT):
+# get_filename_component called with incorrect number of arguments
+# Call Stack (most recent call first):
+# CMakeLists.txt:3 (enable_language)
+#
+# My workaround is to invoke cmake twice. If both return codes are zero,
+# it is safe to invoke ENABLE_LANGUAGE(Fortran OPTIONAL)
+
+function(workaround_9220 language language_works)
+ #message("DEBUG: language = ${language}")
+ set(text
+ "project(test NONE)
+cmake_minimum_required(VERSION 2.6.0)
+enable_language(${language} OPTIONAL)
+"
+ )
+ file(REMOVE_RECURSE ${CMAKE_BINARY_DIR}/language_tests/${language})
+ file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/language_tests/${language})
+ file(WRITE ${CMAKE_BINARY_DIR}/language_tests/${language}/CMakeLists.txt
+ ${text})
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} .
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/language_tests/${language}
+ RESULT_VARIABLE return_code
+ OUTPUT_QUIET
+ ERROR_QUIET
+ )
+
+ if(return_code EQUAL 0)
+ # Second run
+ execute_process (
+ COMMAND ${CMAKE_COMMAND} .
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/language_tests/${language}
+ RESULT_VARIABLE return_code
+ OUTPUT_QUIET
+ ERROR_QUIET
+ )
+ if(return_code EQUAL 0)
+ set(${language_works} ON PARENT_SCOPE)
+ else(return_code EQUAL 0)
+ set(${language_works} OFF PARENT_SCOPE)
+ endif(return_code EQUAL 0)
+ else(return_code EQUAL 0)
+ set(${language_works} OFF PARENT_SCOPE)
+ endif(return_code EQUAL 0)
+endfunction(workaround_9220)
+
+# Temporary tests of the above function.
+#workaround_9220(CXX CXX_language_works)
+#message("CXX_language_works = ${CXX_language_works}")
+#workaround_9220(CXXp CXXp_language_works)
+#message("CXXp_language_works = ${CXXp_language_works}")
--- /dev/null
+MODULES = \
+ AddGMPFlags.cmake \
+ AddMETISFlags.cmake \
+ AddParMETISFlags.cmake \
+ AddUMFPackFlags.cmake \
+ CheckCXX11Features.cmake \
+ CheckSharedPtr.cmake \
+ DuneBoost.cmake \
+ DuneCMakePackageConfigHelpers.cmake \
+ DuneCommonMacros.cmake \
+ DuneCxaDemangle.cmake \
+ DuneDoc.cmake \
+ DuneDoxygen.cmake \
+ DuneMacros.cmake \
+ DuneMPI.cmake \
+ DunePkgConfig.cmake \
+ DuneStreams.cmake \
+ DuneTestMacros.cmake \
+ DuneTests.cmake \
+ FindBoostFusion.cmake \
+ FindGMP.cmake \
+ FindInkscape.cmake \
+ FindMETIS.cmake \
+ FindMProtect.cmake \
+ FindParMETIS.cmake \
+ FindUMFPack.cmake \
+ Headercheck.cmake \
+ LanguageSupport.cmake \
+ UseInkscape.cmake \
+ UseLATEX.cmake
+
+modulesdir = $(datadir)/dune/cmake/modules
+dist_modules_DATA = ${MODULES}
+
+include $(top_srcdir)/am/global-rules
+EXTRA_DIST = CMakeLists.txt
--- /dev/null
+# Module that provides convertion routines using inkscape
+#
+# Provides the following functions:
+#
+# inkscape_generate_png_from_svg([OUTPUT_DIR <output_dir>] <pngfile1.png> [<pngfile2.png> ....])
+#
+# Generates pngfile1, ... from svg input files pngfile1.svg, ....
+# The output directory can be specified with the option OUTPUT_DIR. If it is omitted
+# the files will be generated in CMAKE_CURRENT_BINARY_DIR.
+
+include(CMakeParseArguments)
+
+function(inkscape_generate_png_from_svg)
+ if(NOT INKSCAPE)
+ return()
+ endif(NOT INKSCAPE)
+ cmake_parse_arguments(INKSCAPE "" "OUTPUT_DIR;DPI" "" ${ARGN})
+ if(NOT INKSCAPE_OUTPUT_DIR)
+ set(INKSCAPE_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
+ endif(NOT INKSCAPE_OUTPUT_DIR)
+ if(NOT INKSCAPE_DPI)
+ set(INKSCAPE_DPI 90)
+ endif(NOT INKSCAPE_DPI)
+
+ foreach(pic ${INKSCAPE_UNPARSED_ARGUMENTS})
+ string(REGEX REPLACE "\\.[a-zA-Z]+" ".svg" input ${pic})
+ add_custom_command(OUTPUT ${pic}
+ COMMAND ${INKSCAPE} --export-dpi=${INKSCAPE_DPI} -e ${pic} ${CMAKE_CURRENT_SOURCE_DIR}/${input}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${input}
+ COMMENT "Generating ${INKSCAPE_OUTPUT_DIR}/${pic} from ${CMAKE_CURRENT_SOURCE_DIR}/${input}"
+ WORKING_DIRECTORY ${INKSCAPE_OUTPUT_DIR})
+ endforeach(pic)
+endfunction(inkscape_generate_png_from_svg)
+
+function(inkscape_generate_eps_from_svg)
+ cmake_parse_arguments(INKSCAPE "" "INPUT_DIR;OUTPUT_DIR;DPI" "" ${ARGN})
+ if(NOT INKSCAPE_INPUT_DIR)
+ set(INKSCAPE_INPUT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+ endif(NOT INKSCAPE_INPUT_DIR)
+ if(NOT INKSCAPE_INPUT_DIR)
+ set(INKSCAPE_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
+ endif(NOT INKSCAPE_INPUT_DIR)
+
+ foreach(_pic ${INKSCAPE_UNPARSED_ARGUMENTS})
+ string(REGEX REPLACE "\\.[a-zA-Z]+" ".png" input "${_pic}")
+ string(REGEX REPLACE "\\.[a-zA-Z]+" ".svg" svginput "${_pic}")
+
+ add_custom_target(${input}
+ COMMAND ${INKSCAPE} --export-dpi=${INKSCAPE_DPI} -e ${input} ${CMAKE_CURRENT_SOURCE_DIR}/${svginput}
+ COMMENT "Generating ${INKSCAPE_OUTPUT_DIR}/${svginput} from ${CMAKE_CURRENT_SOURCE_DIR}/${input}")
+ add_custom_command(OUTPUT ${_pic}
+ COMMAND ${CONVERT} ${INKSCAPE_OUTPUT_DIR}/${input} EPS:${_pic}
+ DEPENDS ${input}
+ COMMENT "Converting ${INKSCAPE_OUTPUT_DIR}/${input} to ${INKSCAPE_OUTPUT_DIR}/${_pic}"
+ WORKING_DIRECTORY ${INKSCAPE_OUTPUT_DIR})
+ endforeach(_pic ${INKSCAPE_UNPARSED_ARGUMENTS})
+endfunction(inkscape_generate_eps_from_svg)
--- /dev/null
+# File: UseLATEX.cmake
+# CMAKE commands to actually use the LaTeX compiler
+# Version: 1.10.4
+# Author: Kenneth Moreland <kmorel@sandia.gov>
+#
+# Copyright 2004 Sandia Corporation.
+# Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
+# license for use of this work by or on behalf of the
+# U.S. Government. Redistribution and use in source and binary forms, with
+# or without modification, are permitted provided that this Notice and any
+# statement of authorship are reproduced on all copies.
+#
+# The following function is defined:
+#
+# ADD_LATEX_DOCUMENT(<tex_file>
+# [FATHER_TARGET <father_target>]
+# [BIBFILES <bib_files>]
+# [INPUTS <input_tex_files>]
+# [IMAGE_DIRS] <image_directories>
+# [IMAGES] <image_files>
+# [CONFIGURE] <tex_files>
+# [DEPENDS] <tex_files>
+# [MULTIBIB_NEWCITES] <suffix_list>
+# [USE_INDEX] [USE_GLOSSARY] [USE_NOMENCL]
+# [DEFAULT_PDF] [DEFAULT_SAFEPDF] [DEFAULT_PS] [NO_DEFAULT]
+# [MANGLE_TARGET_NAMES])
+# Adds targets that compile <tex_file>. The latex output is placed
+# in LATEX_OUTPUT_PATH or CMAKE_CURRENT_BINARY_DIR if the former is
+# not set. The latex program is picky about where files are located,
+# so all input files are copied from the source directory to the
+# output directory. This includes the target tex file, any tex file
+# listed with the INPUTS option, the bibliography files listed with
+# the BIBFILES option, and any .cls, .bst, and .clo files found in
+# the current source directory. Images found in the IMAGE_DIRS
+# directories or listed by IMAGES are also copied to the output
+# directory and coverted to an appropriate format if necessary. Any
+# tex files also listed with the CONFIGURE option are also processed
+# with the CMake CONFIGURE_FILE command (with the @ONLY flag). Any
+# file listed in CONFIGURE but not the target tex file or listed with
+# INPUTS has no effect. DEPENDS can be used to specify generated files
+# that are needed to compile the latex target.
+#
+# The following targets are made:
+# dvi: Makes <name>.dvi
+# pdf: Makes <name>.pdf using pdflatex.
+# safepdf: Makes <name>.pdf using ps2pdf. If using the default
+# program arguments, this will ensure all fonts are
+# embedded and no lossy compression has been performed
+# on images.
+# ps: Makes <name>.ps
+# html: Makes <name>.html
+# auxclean: Deletes <name>.aux and other auxiliary files.
+# This is sometimes necessary if a LaTeX error occurs
+# and writes a bad aux file. Unlike the regular clean
+# target, it does not delete other input files, such as
+# converted images, to save time on the rebuild.
+#
+# If FATHER_TARGET is omitted, the dvi target is added to the ALL.
+# That is, it will be the target built by default. If the DEFAULT_PDF
+# argument is given, then the pdf target will be the default instead of
+# dvi. Likewise, DEFAULT_SAFEPDF sets the default target to safepdf.
+# If FATHER_TARGET is set, the files will be a dependency of
+# FATHER_TARGET. By setting FATHER_TARGET to doc, the files will be build
+# during make doc. If NO_DEFAULT
+# is specified, then no target will be added to ALL, which is
+# convenient when including LaTeX documentation with something else.
+#
+# If the argument MANGLE_TARGET_NAMES is given, then each of the
+# target names above will be mangled with the <tex_file> name. This
+# is to make the targets unique if ADD_LATEX_DOCUMENT is called for
+# multiple documents. If the argument USE_INDEX is given, then
+# commands to build an index are made. If the argument USE_GLOSSARY
+# is given, then commands to build a glossary are made. If the
+# argument MULTIBIB_NEWCITES is given, then additional bibtex calls
+# are added to the build to support the extra auxiliary files created
+# with the \newcite command in the multibib package.
+#
+# History:
+#
+# 1.10.4 Copy font files to binary directory for packages that come with
+# their own fonts.
+#
+# 1.10.3 Check for Windows version of convert being used instead of
+# ImageMagick's version (thanks to Martin Baute).
+#
+# 1.10.2 Use htlatex as a fallback when latex2html is not available (thanks
+# to Tomasz Grzegurzko).
+#
+# 1.10.1 Make convert program mandatory only if actually used (thanks to
+# Julien Schueller).
+#
+# 1.10.0 Added NO_DEFAULT and DEFAULT_PS options.
+# Fixed issue with cleaning files for LaTeX documents originating in
+# a subdirectory.
+#
+# 1.9.6 Fixed problem with LATEX_SMALL_IMAGES.
+# Strengthened check to make sure the output directory does not contain
+# the source files.
+#
+# 1.9.5 Add support for image types not directly supported by either latex
+# or pdflatex. (Thanks to Jorge Gerardo Pena Pastor for SVG support.)
+#
+# 1.9.4 Fix issues with filenames containing multiple periods.
+#
+# 1.9.3 Hide some variables that are now cached but should not show up in
+# the ccmake list of variables.
+#
+# 1.9.2 Changed MACRO declarations to FUNCTION declarations. The better
+# FUNCTION scoping will hopefully avoid some common but subtle bugs.
+# This implicitly increases the minimum CMake version to 4.6 (although
+# I honestly only test it with the latest 4.8 version).
+#
+# Since we are updating the minimum CMake version, I'm going to start
+# using the builtin LIST commands that are now available.
+#
+# Favor using pdftops from the Poppler package to convert from pdf to
+# eps. It does a much better job than ImageMagick or ghostscript.
+#
+# 1.9.1 Fixed typo that caused the LATEX_SMALL_IMAGES option to fail to
+# activate.
+#
+# 1.9.0 Add support for the multibib package (thanks to Antonio LaTorre).
+#
+# 1.8.2 Fix corner case when an argument name was also a variable containing
+# the text of an argument. In this case, the CMake IF was matching
+# the argument text with the contents of the variable with the same
+# argument name.
+#
+# 1.8.1 Fix problem where ps2pdf was not getting the appropriate arguments.
+#
+# 1.8.0 Add support for synctex.
+#
+# 1.7.7 Support calling xindy when making glossaries.
+#
+# Improved make clean support.
+#
+# 1.7.6 Add support for the nomencl package (thanks to Myles English).
+#
+# 1.7.5 Fix issue with bibfiles being copied two different ways, which causes
+# Problems with dependencies (thanks to Edwin van Leeuwen).
+#
+# 1.7.4 Added the DEFAULT_SAFEPDF option (thanks to Raymond Wan).
+#
+# Added warnings when image directories are not found (and were
+# probably not given relative to the source directory).
+#
+# 1.7.3 Fix some issues with interactions between makeglossaries and bibtex
+# (thanks to Mark de Wever).
+#
+# 1.7.2 Use ps2pdf to convert eps to pdf to get around the problem with
+# ImageMagick dropping the bounding box (thanks to Lukasz Lis).
+#
+# 1.7.1 Fixed some dependency issues.
+#
+# 1.7.0 Added DEPENDS options (thanks to Theodore Papadopoulo).
+#
+# 1.6.1 Ported the makeglossaries command to CMake and embedded the port
+# into UseLATEX.cmake.
+#
+# 1.6.0 Allow the use of the makeglossaries command. Thanks to Oystein
+# S. Haaland for the patch.
+#
+# 1.5.0 Allow any type of file in the INPUTS lists, not just tex file
+# (suggested by Eric Noulard). As a consequence, the ability to
+# specify tex files without the .tex extension is removed. The removed
+# function is of dubious value anyway.
+#
+# When copying input files, skip over any file that exists in the
+# binary directory but does not exist in the source directory with the
+# assumption that these files were added by some other mechanism. I
+# find this useful when creating large documents with multiple
+# chapters that I want to build separately (for speed) as I work on
+# them. I use the same boilerplate as the starting point for all
+# and just copy it with different configurations. This was what the
+# separate ADD_LATEX_DOCUMENT method was supposed to originally be for.
+# Since its external use is pretty much deprecated, I removed that
+# documentation.
+#
+# 1.4.1 Copy .sty files along with the other class and package files.
+#
+# 1.4.0 Added a MANGLE_TARGET_NAMES option that will mangle the target names.
+#
+# Fixed problem with copying bib files that became apparent with
+# CMake 2.4.
+#
+# 1.3.0 Added a LATEX_OUTPUT_PATH variable that allows you or the user to
+# specify where the built latex documents to go. This is especially
+# handy if you want to do in-source builds.
+#
+# Removed the ADD_LATEX_IMAGES macro and absorbed the functionality
+# into ADD_LATEX_DOCUMENT. The old interface was always kind of
+# clunky anyway since you had to specify the image directory in both
+# places. It also made supporting LATEX_OUTPUT_PATH problematic.
+#
+# Added support for jpeg files.
+#
+# 1.2.0 Changed the configuration options yet again. Removed the NO_CONFIGURE
+# Replaced it with a CONFIGURE option that lists input files for which
+# configure should be run.
+#
+# The pdf target no longer depends on the dvi target. This allows you
+# to build latex documents that require pdflatex. Also added an option
+# to make the pdf target the default one.
+#
+# 1.1.1 Added the NO_CONFIGURE option. The @ character can be used when
+# specifying table column separators. If two or more are used, then
+# will incorrectly substitute them.
+#
+# 1.1.0 Added ability include multiple bib files. Added ability to do copy
+# sub-tex files for multipart tex files.
+#
+# 1.0.0 If both ps and pdf type images exist, just copy the one that
+# matches the current render mode. Replaced a bunch of STRING
+# commands with GET_FILENAME_COMPONENT commands that were made to do
+# the desired function.
+#
+# 0.4.0 First version posted to CMake Wiki.
+#
+
+#############################################################################
+# Find the location of myself while originally executing. If you do this
+# inside of a macro, it will recode where the macro was invoked.
+#############################################################################
+SET(LATEX_USE_LATEX_LOCATION ${CMAKE_CURRENT_LIST_FILE}
+ CACHE INTERNAL "Location of UseLATEX.cmake file." FORCE
+ )
+
+#############################################################################
+# Generic helper functions
+#############################################################################
+
+FUNCTION(LATEX_LIST_CONTAINS var value)
+ SET(input_list ${ARGN})
+ LIST(FIND input_list "${value}" index)
+ IF (index GREATER -1)
+ SET(${var} TRUE PARENT_SCOPE)
+ ELSE (index GREATER -1)
+ SET(${var} PARENT_SCOPE)
+ ENDIF (index GREATER -1)
+ENDFUNCTION(LATEX_LIST_CONTAINS)
+
+# Parse function arguments. Variables containing the results are placed
+# in the global scope for historical reasons.
+FUNCTION(LATEX_PARSE_ARGUMENTS prefix arg_names option_names)
+ SET(DEFAULT_ARGS)
+ FOREACH(arg_name ${arg_names})
+ SET(${prefix}_${arg_name} CACHE INTERNAL "${prefix} argument" FORCE)
+ ENDFOREACH(arg_name)
+ FOREACH(option ${option_names})
+ SET(${prefix}_${option} CACHE INTERNAL "${prefix} option" FORCE)
+ ENDFOREACH(option)
+
+ SET(current_arg_name DEFAULT_ARGS)
+ SET(current_arg_list)
+ FOREACH(arg ${ARGN})
+ LATEX_LIST_CONTAINS(is_arg_name ${arg} ${arg_names})
+ LATEX_LIST_CONTAINS(is_option ${arg} ${option_names})
+ IF (is_arg_name)
+ SET(${prefix}_${current_arg_name} ${current_arg_list}
+ CACHE INTERNAL "${prefix} argument" FORCE)
+ SET(current_arg_name ${arg})
+ SET(current_arg_list)
+ ELSEIF (is_option)
+ SET(${prefix}_${arg} TRUE CACHE INTERNAL "${prefix} option" FORCE)
+ ELSE (is_arg_name)
+ SET(current_arg_list ${current_arg_list} ${arg})
+ ENDIF (is_arg_name)
+ ENDFOREACH(arg)
+ SET(${prefix}_${current_arg_name} ${current_arg_list}
+ CACHE INTERNAL "${prefix} argument" FORCE)
+ENDFUNCTION(LATEX_PARSE_ARGUMENTS)
+
+# Match the contents of a file to a regular expression.
+FUNCTION(LATEX_FILE_MATCH variable filename regexp default)
+ # The FILE STRINGS command would be a bit better, but I'm not totally sure
+ # the match will always be to a whole line, and I don't want to break things.
+ FILE(READ ${filename} file_contents)
+ STRING(REGEX MATCHALL "${regexp}"
+ match_result ${file_contents}
+ )
+ IF (match_result)
+ SET(${variable} "${match_result}" PARENT_SCOPE)
+ ELSE (match_result)
+ SET(${variable} "${default}" PARENT_SCOPE)
+ ENDIF (match_result)
+ENDFUNCTION(LATEX_FILE_MATCH)
+
+# A version of GET_FILENAME_COMPONENT that treats extensions after the last
+# period rather than the first. To the best of my knowledge, all filenames
+# typically used by LaTeX, including image files, have small extensions
+# after the last dot.
+FUNCTION(LATEX_GET_FILENAME_COMPONENT varname filename type)
+ SET(result)
+ IF ("${type}" STREQUAL "NAME_WE")
+ GET_FILENAME_COMPONENT(name ${filename} NAME)
+ STRING(REGEX REPLACE "\\.[^.]*\$" "" result "${name}")
+ ELSEIF ("${type}" STREQUAL "EXT")
+ GET_FILENAME_COMPONENT(name ${filename} NAME)
+ STRING(REGEX MATCH "\\.[^.]*\$" result "${name}")
+ ELSE ("${type}" STREQUAL "NAME_WE")
+ GET_FILENAME_COMPONENT(result ${filename} ${type})
+ ENDIF ("${type}" STREQUAL "NAME_WE")
+ SET(${varname} "${result}" PARENT_SCOPE)
+ENDFUNCTION(LATEX_GET_FILENAME_COMPONENT)
+
+#############################################################################
+# Functions that perform processing during a LaTeX build.
+#############################################################################
+FUNCTION(LATEX_MAKEGLOSSARIES)
+ # This is really a bare bones port of the makeglossaries perl script into
+ # CMake scripting.
+ MESSAGE("**************************** In makeglossaries")
+ IF (NOT LATEX_TARGET)
+ MESSAGE(SEND_ERROR "Need to define LATEX_TARGET")
+ ENDIF (NOT LATEX_TARGET)
+
+ SET(aux_file ${LATEX_TARGET}.aux)
+
+ IF (NOT EXISTS ${aux_file})
+ MESSAGE(SEND_ERROR "${aux_file} does not exist. Run latex on your target file.")
+ ENDIF (NOT EXISTS ${aux_file})
+
+ LATEX_FILE_MATCH(newglossary_lines ${aux_file}
+ "@newglossary[ \t]*{([^}]*)}{([^}]*)}{([^}]*)}{([^}]*)}"
+ "@newglossary{main}{glg}{gls}{glo}"
+ )
+
+ LATEX_FILE_MATCH(istfile_line ${aux_file}
+ "@istfilename[ \t]*{([^}]*)}"
+ "@istfilename{${LATEX_TARGET}.ist}"
+ )
+ STRING(REGEX REPLACE "@istfilename[ \t]*{([^}]*)}" "\\1"
+ istfile ${istfile_line}
+ )
+
+ STRING(REGEX MATCH ".*\\.xdy" use_xindy "${istfile}")
+ IF (use_xindy)
+ MESSAGE("*************** Using xindy")
+ IF (NOT XINDY_COMPILER)
+ MESSAGE(SEND_ERROR "Need to define XINDY_COMPILER")
+ ENDIF (NOT XINDY_COMPILER)
+ ELSE (use_xindy)
+ MESSAGE("*************** Using makeindex")
+ IF (NOT MAKEINDEX_COMPILER)
+ MESSAGE(SEND_ERROR "Need to define MAKEINDEX_COMPILER")
+ ENDIF (NOT MAKEINDEX_COMPILER)
+ ENDIF (use_xindy)
+
+ FOREACH(newglossary ${newglossary_lines})
+ STRING(REGEX REPLACE
+ "@newglossary[ \t]*{([^}]*)}{([^}]*)}{([^}]*)}{([^}]*)}"
+ "\\1" glossary_name ${newglossary}
+ )
+ STRING(REGEX REPLACE
+ "@newglossary[ \t]*{([^}]*)}{([^}]*)}{([^}]*)}{([^}]*)}"
+ "${LATEX_TARGET}.\\2" glossary_log ${newglossary}
+ )
+ STRING(REGEX REPLACE
+ "@newglossary[ \t]*{([^}]*)}{([^}]*)}{([^}]*)}{([^}]*)}"
+ "${LATEX_TARGET}.\\3" glossary_out ${newglossary}
+ )
+ STRING(REGEX REPLACE
+ "@newglossary[ \t]*{([^}]*)}{([^}]*)}{([^}]*)}{([^}]*)}"
+ "${LATEX_TARGET}.\\4" glossary_in ${newglossary}
+ )
+
+ IF (use_xindy)
+ LATEX_FILE_MATCH(xdylanguage_line ${aux_file}
+ "@xdylanguage[ \t]*{${glossary_name}}{([^}]*)}"
+ "@xdylanguage{${glossary_name}}{english}"
+ )
+ STRING(REGEX REPLACE
+ "@xdylanguage[ \t]*{${glossary_name}}{([^}]*)}"
+ "\\1"
+ language
+ ${xdylanguage_line}
+ )
+ # What crazy person makes a LaTeX index generater that uses different
+ # identifiers for language than babel (or at least does not support
+ # the old ones)?
+ IF (${language} STREQUAL "frenchb")
+ SET(language "french")
+ ELSEIF (${language} MATCHES "^n?germanb?$")
+ SET(language "german")
+ ELSEIF (${language} STREQUAL "magyar")
+ SET(language "hungarian")
+ ELSEIF (${language} STREQUAL "lsorbian")
+ SET(language "lower-sorbian")
+ ELSEIF (${language} STREQUAL "norsk")
+ SET(language "norwegian")
+ ELSEIF (${language} STREQUAL "portuges")
+ SET(language "portuguese")
+ ELSEIF (${language} STREQUAL "russianb")
+ SET(language "russian")
+ ELSEIF (${language} STREQUAL "slovene")
+ SET(language "slovenian")
+ ELSEIF (${language} STREQUAL "ukraineb")
+ SET(language "ukrainian")
+ ELSEIF (${language} STREQUAL "usorbian")
+ SET(language "upper-sorbian")
+ ENDIF (${language} STREQUAL "frenchb")
+ IF (language)
+ SET(language_flags "-L ${language}")
+ ELSE (language)
+ SET(language_flags "")
+ ENDIF (language)
+
+ LATEX_FILE_MATCH(codepage_line ${aux_file}
+ "@gls@codepage[ \t]*{${glossary_name}}{([^}]*)}"
+ "@gls@codepage{${glossary_name}}{utf}"
+ )
+ STRING(REGEX REPLACE
+ "@gls@codepage[ \t]*{${glossary_name}}{([^}]*)}"
+ "\\1"
+ codepage
+ ${codepage_line}
+ )
+ IF (codepage)
+ SET(codepage_flags "-C ${codepage}")
+ ELSE (codepage)
+ # Ideally, we would check that the language is compatible with the
+ # default codepage, but I'm hoping that distributions will be smart
+ # enough to specify their own codepage. I know, it's asking a lot.
+ SET(codepage_flags "")
+ ENDIF (codepage)
+
+ MESSAGE("${XINDY_COMPILER} ${MAKEGLOSSARIES_COMPILER_FLAGS} ${language_flags} ${codepage_flags} -I xindy -M ${glossary_name} -t ${glossary_log} -o ${glossary_out} ${glossary_in}"
+ )
+ EXEC_PROGRAM(${XINDY_COMPILER}
+ ARGS ${MAKEGLOSSARIES_COMPILER_FLAGS}
+ ${language_flags}
+ ${codepage_flags}
+ -I xindy
+ -M ${glossary_name}
+ -t ${glossary_log}
+ -o ${glossary_out}
+ ${glossary_in}
+ OUTPUT_VARIABLE xindy_output
+ )
+ MESSAGE("${xindy_output}")
+
+ # So, it is possible (perhaps common?) for aux files to specify a
+ # language and codepage that are incompatible with each other. Check
+ # for that condition, and if it happens run again with the default
+ # codepage.
+ IF ("${xindy_output}" MATCHES "^Cannot locate xindy module for language (.+) in codepage (.+)\\.$")
+ MESSAGE("*************** Retrying xindy with default codepage.")
+ EXEC_PROGRAM(${XINDY_COMPILER}
+ ARGS ${MAKEGLOSSARIES_COMPILER_FLAGS}
+ ${language_flags}
+ -I xindy
+ -M ${glossary_name}
+ -t ${glossary_log}
+ -o ${glossary_out}
+ ${glossary_in}
+ )
+ ENDIF ("${xindy_output}" MATCHES "^Cannot locate xindy module for language (.+) in codepage (.+)\\.$")
+ #ENDIF ("${xindy_output}" MATCHES "Cannot locate xindy module for language (.+) in codepage (.+)\\.")
+
+ ELSE (use_xindy)
+ MESSAGE("${MAKEINDEX_COMPILER} ${MAKEGLOSSARIES_COMPILER_FLAGS} -s ${istfile} -t ${glossary_log} -o ${glossary_out} ${glossary_in}")
+ EXEC_PROGRAM(${MAKEINDEX_COMPILER} ARGS ${MAKEGLOSSARIES_COMPILER_FLAGS}
+ -s ${istfile} -t ${glossary_log} -o ${glossary_out} ${glossary_in}
+ )
+ ENDIF (use_xindy)
+
+ ENDFOREACH(newglossary)
+ENDFUNCTION(LATEX_MAKEGLOSSARIES)
+
+FUNCTION(LATEX_MAKENOMENCLATURE)
+ MESSAGE("**************************** In makenomenclature")
+ IF (NOT LATEX_TARGET)
+ MESSAGE(SEND_ERROR "Need to define LATEX_TARGET")
+ ENDIF (NOT LATEX_TARGET)
+
+ IF (NOT MAKEINDEX_COMPILER)
+ MESSAGE(SEND_ERROR "Need to define MAKEINDEX_COMPILER")
+ ENDIF (NOT MAKEINDEX_COMPILER)
+
+ SET(nomencl_out ${LATEX_TARGET}.nls)
+ SET(nomencl_in ${LATEX_TARGET}.nlo)
+
+ EXEC_PROGRAM(${MAKEINDEX_COMPILER} ARGS ${MAKENOMENCLATURE_COMPILER_FLAGS}
+ ${nomencl_in} -s "nomencl.ist" -o ${nomencl_out}
+ )
+ENDFUNCTION(LATEX_MAKENOMENCLATURE)
+
+FUNCTION(LATEX_CORRECT_SYNCTEX)
+ MESSAGE("**************************** In correct SyncTeX")
+ IF (NOT LATEX_TARGET)
+ MESSAGE(SEND_ERROR "Need to define LATEX_TARGET")
+ ENDIF (NOT LATEX_TARGET)
+
+ IF (NOT GZIP)
+ MESSAGE(SEND_ERROR "Need to define GZIP")
+ ENDIF (NOT GZIP)
+
+ IF (NOT LATEX_SOURCE_DIRECTORY)
+ MESSAGE(SEND_ERROR "Need to define LATEX_SOURCE_DIRECTORY")
+ ENDIF (NOT LATEX_SOURCE_DIRECTORY)
+
+ IF (NOT LATEX_BINARY_DIRECTORY)
+ MESSAGE(SEND_ERROR "Need to define LATEX_BINARY_DIRECTORY")
+ ENDIF (NOT LATEX_BINARY_DIRECTORY)
+
+ SET(synctex_file ${LATEX_BINARY_DIRECTORY}/${LATEX_TARGET}.synctex)
+ SET(synctex_file_gz ${synctex_file}.gz)
+
+ IF (EXISTS ${synctex_file_gz})
+
+ MESSAGE("Making backup of synctex file.")
+ CONFIGURE_FILE(${synctex_file_gz} ${synctex_file}.bak.gz COPYONLY)
+
+ MESSAGE("Uncompressing synctex file.")
+ EXEC_PROGRAM(${GZIP}
+ ARGS --decompress ${synctex_file_gz}
+ )
+
+ MESSAGE("Reading synctex file.")
+ FILE(READ ${synctex_file} synctex_data)
+
+ MESSAGE("Replacing relative with absolute paths.")
+ STRING(REGEX REPLACE
+ "(Input:[0-9]+:)([^/\n][^\n]*)"
+ "\\1${LATEX_SOURCE_DIRECTORY}/\\2"
+ synctex_data
+ "${synctex_data}"
+ )
+
+ MESSAGE("Writing synctex file.")
+ FILE(WRITE ${synctex_file} "${synctex_data}")
+
+ MESSAGE("Compressing synctex file.")
+ EXEC_PROGRAM(${GZIP}
+ ARGS ${synctex_file}
+ )
+
+ ELSE (EXISTS ${synctex_file_gz})
+
+ MESSAGE(SEND_ERROR "File ${synctex_file_gz} not found. Perhaps synctex is not supported by your LaTeX compiler.")
+
+ ENDIF (EXISTS ${synctex_file_gz})
+
+ENDFUNCTION(LATEX_CORRECT_SYNCTEX)
+
+#############################################################################
+# Helper functions for establishing LaTeX build.
+#############################################################################
+
+FUNCTION(LATEX_NEEDIT VAR NAME)
+ IF (NOT ${VAR})
+ MESSAGE(SEND_ERROR "I need the ${NAME} command.")
+ ENDIF(NOT ${VAR})
+ENDFUNCTION(LATEX_NEEDIT)
+
+FUNCTION(LATEX_WANTIT VAR NAME)
+ IF (NOT ${VAR})
+ MESSAGE(STATUS "I could not find the ${NAME} command.")
+ ENDIF(NOT ${VAR})
+ENDFUNCTION(LATEX_WANTIT)
+
+FUNCTION(LATEX_SETUP_VARIABLES)
+ SET(LATEX_OUTPUT_PATH "${LATEX_OUTPUT_PATH}"
+ CACHE PATH "If non empty, specifies the location to place LaTeX output."
+ )
+
+ FIND_PACKAGE(LATEX)
+
+ FIND_PROGRAM(XINDY_COMPILER
+ NAME xindy
+ PATHS ${MIKTEX_BINARY_PATH} /usr/bin
+ )
+
+ FIND_PACKAGE(UnixCommands)
+
+ FIND_PROGRAM(PDFTOPS_CONVERTER
+ NAMES pdftops
+ DOC "The pdf to ps converter program from the Poppler package."
+ )
+
+ MARK_AS_ADVANCED(CLEAR
+ LATEX_COMPILER
+ PDFLATEX_COMPILER
+ BIBTEX_COMPILER
+ MAKEINDEX_COMPILER
+ XINDY_COMPILER
+ DVIPS_CONVERTER
+ PS2PDF_CONVERTER
+ PDFTOPS_CONVERTER
+ LATEX2HTML_CONVERTER
+ )
+
+ LATEX_NEEDIT(LATEX_COMPILER latex)
+ LATEX_WANTIT(PDFLATEX_COMPILER pdflatex)
+ LATEX_NEEDIT(BIBTEX_COMPILER bibtex)
+ LATEX_NEEDIT(MAKEINDEX_COMPILER makeindex)
+ LATEX_WANTIT(DVIPS_CONVERTER dvips)
+ LATEX_WANTIT(PS2PDF_CONVERTER ps2pdf)
+ LATEX_WANTIT(PDFTOPS_CONVERTER pdftops)
+ # MiKTeX calls latex2html htlatex
+ IF (NOT ${LATEX2HTML_CONVERTER})
+ FIND_PROGRAM(HTLATEX_CONVERTER
+ NAMES htlatex
+ PATHS ${MIKTEX_BINARY_PATH}
+ /usr/bin
+ )
+ IF (HTLATEX_CONVERTER)
+ SET(USING_HTLATEX TRUE CACHE INTERNAL "True when using MiKTeX htlatex instead of latex2html" FORCE)
+ SET(LATEX2HTML_CONVERTER ${HTLATEX_CONVERTER}
+ CACHE FILEPATH "htlatex taking the place of latex2html" FORCE)
+ ELSE (HTLATEX_CONVERTER)
+ SET(USING_HTLATEX FALSE CACHE INTERNAL "True when using MiKTeX htlatex instead of latex2html" FORCE)
+ ENDIF (HTLATEX_CONVERTER)
+ ENDIF (NOT ${LATEX2HTML_CONVERTER})
+ LATEX_WANTIT(LATEX2HTML_CONVERTER latex2html)
+
+ SET(LATEX_COMPILER_FLAGS "-interaction=nonstopmode"
+ CACHE STRING "Flags passed to latex.")
+ SET(PDFLATEX_COMPILER_FLAGS ${LATEX_COMPILER_FLAGS}
+ CACHE STRING "Flags passed to pdflatex.")
+ SET(LATEX_SYNCTEX_FLAGS "-synctex=1"
+ CACHE STRING "latex/pdflatex flags used to create synctex file.")
+ SET(BIBTEX_COMPILER_FLAGS ""
+ CACHE STRING "Flags passed to bibtex.")
+ SET(MAKEINDEX_COMPILER_FLAGS ""
+ CACHE STRING "Flags passed to makeindex.")
+ SET(MAKEGLOSSARIES_COMPILER_FLAGS ""
+ CACHE STRING "Flags passed to makeglossaries.")
+ SET(MAKENOMENCLATURE_COMPILER_FLAGS ""
+ CACHE STRING "Flags passed to makenomenclature.")
+ SET(DVIPS_CONVERTER_FLAGS "-Ppdf -G0 -t letter"
+ CACHE STRING "Flags passed to dvips.")
+ SET(PS2PDF_CONVERTER_FLAGS "-dMaxSubsetPct=100 -dCompatibilityLevel=1.3 -dSubsetFonts=true -dEmbedAllFonts=true -dAutoFilterColorImages=false -dAutoFilterGrayImages=false -dColorImageFilter=/FlateEncode -dGrayImageFilter=/FlateEncode -dMonoImageFilter=/FlateEncode"
+ CACHE STRING "Flags passed to ps2pdf.")
+ SET(PDFTOPS_CONVERTER_FLAGS -r 600
+ CACHE STRING "Flags passed to pdftops.")
+ SET(LATEX2HTML_CONVERTER_FLAGS ""
+ CACHE STRING "Flags passed to latex2html.")
+ MARK_AS_ADVANCED(
+ LATEX_COMPILER_FLAGS
+ PDFLATEX_COMPILER_FLAGS
+ LATEX_SYNCTEX_FLAGS
+ BIBTEX_COMPILER_FLAGS
+ MAKEINDEX_COMPILER_FLAGS
+ MAKEGLOSSARIES_COMPILER_FLAGS
+ MAKENOMENCLATURE_COMPILER_FLAGS
+ DVIPS_CONVERTER_FLAGS
+ PS2PDF_CONVERTER_FLAGS
+ PDFTOPS_CONVERTER_FLAGS
+ LATEX2HTML_CONVERTER_FLAGS
+ )
+ SEPARATE_ARGUMENTS(LATEX_COMPILER_FLAGS)
+ SEPARATE_ARGUMENTS(PDFLATEX_COMPILER_FLAGS)
+ SEPARATE_ARGUMENTS(LATEX_SYNCTEX_FLAGS)
+ SEPARATE_ARGUMENTS(BIBTEX_COMPILER_FLAGS)
+ SEPARATE_ARGUMENTS(MAKEINDEX_COMPILER_FLAGS)
+ SEPARATE_ARGUMENTS(MAKEGLOSSARIES_COMPILER_FLAGS)
+ SEPARATE_ARGUMENTS(MAKENOMENCLATURE_COMPILER_FLAGS)
+ SEPARATE_ARGUMENTS(DVIPS_CONVERTER_FLAGS)
+ SEPARATE_ARGUMENTS(PS2PDF_CONVERTER_FLAGS)
+ SEPARATE_ARGUMENTS(PDFTOPS_CONVERTER_FLAGS)
+ SEPARATE_ARGUMENTS(LATEX2HTML_CONVERTER_FLAGS)
+
+ FIND_PROGRAM(IMAGEMAGICK_CONVERT convert
+ DOC "The convert program that comes with ImageMagick (available at http://www.imagemagick.org)."
+ )
+
+ OPTION(LATEX_USE_SYNCTEX
+ "If on, have LaTeX generate a synctex file, which WYSIWYG editors can use to correlate output files like dvi and pdf with the lines of LaTeX source that generates them. In addition to adding the LATEX_SYNCTEX_FLAGS to the command line, this option also adds build commands that \"corrects\" the resulting synctex file to point to the original LaTeX files rather than those generated by UseLATEX.cmake."
+ OFF
+ )
+
+ OPTION(LATEX_SMALL_IMAGES
+ "If on, the raster images will be converted to 1/6 the original size. This is because papers usually require 600 dpi images whereas most monitors only require at most 96 dpi. Thus, smaller images make smaller files for web distributation and can make it faster to read dvi files."
+ OFF)
+ IF (LATEX_SMALL_IMAGES)
+ SET(LATEX_RASTER_SCALE 16 PARENT_SCOPE)
+ SET(LATEX_OPPOSITE_RASTER_SCALE 100 PARENT_SCOPE)
+ ELSE (LATEX_SMALL_IMAGES)
+ SET(LATEX_RASTER_SCALE 100 PARENT_SCOPE)
+ SET(LATEX_OPPOSITE_RASTER_SCALE 16 PARENT_SCOPE)
+ ENDIF (LATEX_SMALL_IMAGES)
+
+ # Just holds extensions for known image types. They should all be lower case.
+ # For historical reasons, these are all declared in the global scope.
+ SET(LATEX_DVI_VECTOR_IMAGE_EXTENSIONS .eps CACHE INTERNAL "")
+ SET(LATEX_DVI_RASTER_IMAGE_EXTENSIONS CACHE INTERNAL "")
+ SET(LATEX_DVI_IMAGE_EXTENSIONS
+ ${LATEX_DVI_VECTOR_IMAGE_EXTENSIONS}
+ ${LATEX_DVI_RASTER_IMAGE_EXTENSIONS}
+ CACHE INTERNAL ""
+ )
+
+ SET(LATEX_PDF_VECTOR_IMAGE_EXTENSIONS .pdf CACHE INTERNAL "")
+ SET(LATEX_PDF_RASTER_IMAGE_EXTENSIONS .png .jpeg .jpg CACHE INTERNAL "")
+ SET(LATEX_PDF_IMAGE_EXTENSIONS
+ ${LATEX_PDF_VECTOR_IMAGE_EXTENSIONS}
+ ${LATEX_PDF_RASTER_IMAGE_EXTENSIONS}
+ CACHE INTERNAL ""
+ )
+
+ SET(LATEX_OTHER_VECTOR_IMAGE_EXTENSIONS .svg CACHE INTERNAL "")
+ SET(LATEX_OTHER_RASTER_IMAGE_EXTENSIONS .tif .tiff .gif CACHE INTERNAL "")
+ SET(LATEX_OTHER_IMAGE_EXTENSIONS
+ ${LATEX_OTHER_VECTOR_IMAGE_EXTENSIONS}
+ ${LATEX_OTHER_RASTER_IMAGE_EXTENSIONS}
+ CACHE INTERNAL ""
+ )
+
+ SET(LATEX_VECTOR_IMAGE_EXTENSIONS
+ ${LATEX_DVI_VECTOR_IMAGE_EXTENSIONS}
+ ${LATEX_PDF_VECTOR_IMAGE_EXTENSIONS}
+ ${LATEX_OTHER_VECTOR_IMAGE_EXTENSIONS}
+ CACHE INTERNAL ""
+ )
+ SET(LATEX_RASTER_IMAGE_EXTENSIONS
+ ${LATEX_DVI_RASTER_IMAGE_EXTENSIONS}
+ ${LATEX_PDF_RASTER_IMAGE_EXTENSIONS}
+ ${LATEX_OTHER_RASTER_IMAGE_EXTENSIONS}
+ CACHE INTERNAL ""
+ )
+ SET(LATEX_IMAGE_EXTENSIONS
+ ${LATEX_DVI_IMAGE_EXTENSIONS}
+ ${LATEX_PDF_IMAGE_EXTENSIONS}
+ ${LATEX_OTHER_IMAGE_EXTENSIONS}
+ CACHE INTERNAL ""
+ )
+ENDFUNCTION(LATEX_SETUP_VARIABLES)
+
+FUNCTION(LATEX_GET_OUTPUT_PATH var)
+ SET(latex_output_path)
+ IF (LATEX_OUTPUT_PATH)
+ GET_FILENAME_COMPONENT(
+ LATEX_OUTPUT_PATH_FULL "${LATEX_OUTPUT_PATH}" ABSOLUTE
+ )
+ IF ("${LATEX_OUTPUT_PATH_FULL}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
+ MESSAGE(SEND_ERROR "You cannot set LATEX_OUTPUT_PATH to the same directory that contains LaTeX input files.")
+ ELSE ("${LATEX_OUTPUT_PATH_FULL}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
+ SET(latex_output_path "${LATEX_OUTPUT_PATH_FULL}")
+ ENDIF ("${LATEX_OUTPUT_PATH_FULL}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
+ ELSE (LATEX_OUTPUT_PATH)
+ IF ("${CMAKE_CURRENT_BINARY_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
+ MESSAGE(SEND_ERROR "LaTeX files must be built out of source or you must set LATEX_OUTPUT_PATH.")
+ ELSE ("${CMAKE_CURRENT_BINARY_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
+ SET(latex_output_path "${CMAKE_CURRENT_BINARY_DIR}")
+ ENDIF ("${CMAKE_CURRENT_BINARY_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
+ ENDIF (LATEX_OUTPUT_PATH)
+ SET(${var} ${latex_output_path} PARENT_SCOPE)
+ENDFUNCTION(LATEX_GET_OUTPUT_PATH)
+
+FUNCTION(LATEX_ADD_CONVERT_COMMAND
+ output_path
+ input_path
+ output_extension
+ input_extension
+ flags
+ )
+ SET (require_imagemagick_convert TRUE)
+ SET (convert_flags "")
+ IF (${input_extension} STREQUAL ".eps" AND ${output_extension} STREQUAL ".pdf")
+ # ImageMagick has broken eps to pdf conversion
+ # use ps2pdf instead
+ IF (PS2PDF_CONVERTER)
+ SET (require_imagemagick_convert FALSE)
+ SET (converter ${PS2PDF_CONVERTER})
+ SET (convert_flags -dEPSCrop ${PS2PDF_CONVERTER_FLAGS})
+ ELSE (PS2PDF_CONVERTER)
+ MESSAGE(SEND_ERROR "Using postscript files with pdflatex requires ps2pdf for conversion.")
+ ENDIF (PS2PDF_CONVERTER)
+ ELSEIF (${input_extension} STREQUAL ".pdf" AND ${output_extension} STREQUAL ".eps")
+ # ImageMagick can also be sketchy on pdf to eps conversion. Not good with
+ # color spaces and tends to unnecessarily rasterize.
+ # use pdftops instead
+ IF (PDFTOPS_CONVERTER)
+ SET (require_imagemagick_convert FALSE)
+ SET(converter ${PDFTOPS_CONVERTER})
+ SET(convert_flags -eps ${PDFTOPS_CONVERTER_FLAGS})
+ ELSE (PDFTOPS_CONVERTER)
+ MESSAGE(STATUS "Consider getting pdftops from Poppler to convert PDF images to EPS images.")
+ SET (convert_flags ${flags})
+ ENDIF (PDFTOPS_CONVERTER)
+ ELSE (${input_extension} STREQUAL ".eps" AND ${output_extension} STREQUAL ".pdf")
+ SET (convert_flags ${flags})
+ ENDIF (${input_extension} STREQUAL ".eps" AND ${output_extension} STREQUAL ".pdf")
+
+ IF (require_imagemagick_convert)
+ IF (IMAGEMAGICK_CONVERT)
+ IF (${IMAGEMAGICK_CONVERT} MATCHES "system32[/\\\\]convert\\.exe")
+ MESSAGE(SEND_ERROR "IMAGEMAGICK_CONVERT set to Window's convert.exe for changing file systems rather than ImageMagick's convert for changing image formats. Please make sure ImageMagick is installed (available at http://www.imagemagick.org) and it's convert program is used for IMAGEMAGICK_CONVERT. (It is helpful if ImageMagick's path is before the Windows system paths.)")
+ ELSE (${IMAGEMAGICK_CONVERT} MATCHES "system32[/\\\\]convert\\.exe")
+ SET (converter ${IMAGEMAGICK_CONVERT})
+ ENDIF (${IMAGEMAGICK_CONVERT} MATCHES "system32[/\\\\]convert\\.exe")
+ ELSE (IMAGEMAGICK_CONVERT)
+ MESSAGE(SEND_ERROR "Could not find convert program. Please download ImageMagick from http://www.imagemagick.org and install.")
+ ENDIF (IMAGEMAGICK_CONVERT)
+ ENDIF (require_imagemagick_convert)
+
+ ADD_CUSTOM_COMMAND(OUTPUT ${output_path}
+ COMMAND ${converter}
+ ARGS ${convert_flags} ${input_path} ${output_path}
+ DEPENDS ${input_path}
+ )
+ENDFUNCTION(LATEX_ADD_CONVERT_COMMAND)
+
+# Makes custom commands to convert a file to a particular type.
+FUNCTION(LATEX_CONVERT_IMAGE
+ output_files_var
+ input_file
+ output_extension
+ convert_flags
+ output_extensions
+ other_files
+ )
+ SET(output_file_list)
+ SET(input_dir ${CMAKE_CURRENT_SOURCE_DIR})
+ LATEX_GET_OUTPUT_PATH(output_dir)
+
+ LATEX_GET_FILENAME_COMPONENT(extension "${input_file}" EXT)
+
+ # Check input filename for potential problems with LaTeX.
+ LATEX_GET_FILENAME_COMPONENT(name "${input_file}" NAME_WE)
+ IF (name MATCHES ".*\\..*")
+ STRING(REPLACE "." "-" suggested_name "${name}")
+ SET(suggested_name "${suggested_name}${extension}")
+ MESSAGE(WARNING "Some LaTeX distributions have problems with image file names with multiple extensions. Consider changing ${name}${extension} to something like ${suggested_name}.")
+ ENDIF (name MATCHES ".*\\..*")
+
+ STRING(REGEX REPLACE "\\.[^.]*\$" ${output_extension} output_file
+ "${input_file}")
+
+ LATEX_LIST_CONTAINS(is_type ${extension} ${output_extensions})
+ IF (is_type)
+ IF (convert_flags)
+ LATEX_ADD_CONVERT_COMMAND(${output_dir}/${output_file}
+ ${input_dir}/${input_file} ${output_extension} ${extension}
+ "${convert_flags}")
+ SET(output_file_list ${output_file_list} ${output_dir}/${output_file})
+ ELSE (convert_flags)
+ # As a shortcut, we can just copy the file.
+ ADD_CUSTOM_COMMAND(OUTPUT ${output_dir}/${input_file}
+ COMMAND ${CMAKE_COMMAND}
+ ARGS -E copy ${input_dir}/${input_file} ${output_dir}/${input_file}
+ DEPENDS ${input_dir}/${input_file}
+ )
+ SET(output_file_list ${output_file_list} ${output_dir}/${input_file})
+ ENDIF (convert_flags)
+ ELSE (is_type)
+ SET(do_convert TRUE)
+ # Check to see if there is another input file of the appropriate type.
+ FOREACH(valid_extension ${output_extensions})
+ STRING(REGEX REPLACE "\\.[^.]*\$" ${output_extension} try_file
+ "${input_file}")
+ LATEX_LIST_CONTAINS(has_native_file "${try_file}" ${other_files})
+ IF (has_native_file)
+ SET(do_convert FALSE)
+ ENDIF (has_native_file)
+ ENDFOREACH(valid_extension)
+
+ # If we still need to convert, do it.
+ IF (do_convert)
+ LATEX_ADD_CONVERT_COMMAND(${output_dir}/${output_file}
+ ${input_dir}/${input_file} ${output_extension} ${extension}
+ "${convert_flags}")
+ SET(output_file_list ${output_file_list} ${output_dir}/${output_file})
+ ENDIF (do_convert)
+ ENDIF (is_type)
+
+ SET(${output_files_var} ${output_file_list} PARENT_SCOPE)
+ENDFUNCTION(LATEX_CONVERT_IMAGE)
+
+# Adds custom commands to process the given files for dvi and pdf builds.
+# Adds the output files to the given variables (does not replace).
+FUNCTION(LATEX_PROCESS_IMAGES dvi_outputs_var pdf_outputs_var)
+ LATEX_GET_OUTPUT_PATH(output_dir)
+ SET(dvi_outputs)
+ SET(pdf_outputs)
+ FOREACH(file ${ARGN})
+ IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
+ LATEX_GET_FILENAME_COMPONENT(extension "${file}" EXT)
+ SET(convert_flags)
+
+ # Check to see if we need to downsample the image.
+ LATEX_LIST_CONTAINS(is_raster "${extension}"
+ ${LATEX_RASTER_IMAGE_EXTENSIONS})
+ IF (LATEX_SMALL_IMAGES)
+ IF (is_raster)
+ SET(convert_flags -resize ${LATEX_RASTER_SCALE}%)
+ ENDIF (is_raster)
+ ENDIF (LATEX_SMALL_IMAGES)
+
+ # Make sure the output directory exists.
+ LATEX_GET_FILENAME_COMPONENT(path "${output_dir}/${file}" PATH)
+ MAKE_DIRECTORY("${path}")
+
+ # Do conversions for dvi.
+ LATEX_CONVERT_IMAGE(output_files "${file}" .eps "${convert_flags}"
+ "${LATEX_DVI_IMAGE_EXTENSIONS}" "${ARGN}")
+ SET(dvi_outputs ${dvi_outputs} ${output_files})
+
+ # Do conversions for pdf.
+ IF (is_raster)
+ LATEX_CONVERT_IMAGE(output_files "${file}" .png "${convert_flags}"
+ "${LATEX_PDF_IMAGE_EXTENSIONS}" "${ARGN}")
+ SET(pdf_outputs ${pdf_outputs} ${output_files})
+ ELSE (is_raster)
+ LATEX_CONVERT_IMAGE(output_files "${file}" .pdf "${convert_flags}"
+ "${LATEX_PDF_IMAGE_EXTENSIONS}" "${ARGN}")
+ SET(pdf_outputs ${pdf_outputs} ${output_files})
+ ENDIF (is_raster)
+ ELSE (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
+ MESSAGE(WARNING "Could not find file ${CMAKE_CURRENT_SOURCE_DIR}/${file}. Are you sure you gave relative paths to IMAGES?")
+ ENDIF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
+ ENDFOREACH(file)
+
+ SET(${dvi_outputs_var} ${dvi_outputs} PARENT_SCOPE)
+ SET(${pdf_outputs_var} ${pdf_outputs} PARENT_SCOPE)
+ENDFUNCTION(LATEX_PROCESS_IMAGES)
+
+FUNCTION(ADD_LATEX_IMAGES)
+ MESSAGE(SEND_ERROR "The ADD_LATEX_IMAGES function is deprecated. Image directories are specified with LATEX_ADD_DOCUMENT.")
+ENDFUNCTION(ADD_LATEX_IMAGES)
+
+FUNCTION(LATEX_COPY_GLOBBED_FILES pattern dest)
+ FILE(GLOB file_list ${pattern})
+ FOREACH(in_file ${file_list})
+ LATEX_GET_FILENAME_COMPONENT(out_file ${in_file} NAME)
+ CONFIGURE_FILE(${in_file} ${dest}/${out_file} COPYONLY)
+ ENDFOREACH(in_file)
+ENDFUNCTION(LATEX_COPY_GLOBBED_FILES)
+
+FUNCTION(LATEX_COPY_INPUT_FILE file)
+ LATEX_GET_OUTPUT_PATH(output_dir)
+
+ IF (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file})
+ LATEX_GET_FILENAME_COMPONENT(path ${file} PATH)
+ FILE(MAKE_DIRECTORY ${output_dir}/${path})
+
+ LATEX_LIST_CONTAINS(use_config ${file} ${LATEX_CONFIGURE})
+ IF (use_config)
+ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${file}
+ ${output_dir}/${file}
+ @ONLY
+ )
+ ADD_CUSTOM_COMMAND(OUTPUT ${output_dir}/${file}
+ COMMAND ${CMAKE_COMMAND}
+ ARGS ${CMAKE_BINARY_DIR}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${file}
+ )
+ ELSE (use_config)
+ ADD_CUSTOM_COMMAND(OUTPUT ${output_dir}/${file}
+ COMMAND ${CMAKE_COMMAND}
+ ARGS -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${file} ${output_dir}/${file}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${file}
+ )
+ ENDIF (use_config)
+ ELSE (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file})
+ IF (EXISTS ${output_dir}/${file})
+ # Special case: output exists but input does not. Assume that it was
+ # created elsewhere and skip the input file copy.
+ ELSE (EXISTS ${output_dir}/${file})
+ MESSAGE("Could not find input file ${CMAKE_CURRENT_SOURCE_DIR}/${file}")
+ ENDIF (EXISTS ${output_dir}/${file})
+ ENDIF (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file})
+ENDFUNCTION(LATEX_COPY_INPUT_FILE)
+
+#############################################################################
+# Commands provided by the UseLATEX.cmake "package"
+#############################################################################
+
+FUNCTION(LATEX_USAGE command message)
+ MESSAGE(SEND_ERROR
+ "${message}\nUsage: ${command}(<tex_file>\n [BIBFILES <bib_file> <bib_file> ...]\n [INPUTS <tex_file> <tex_file> ...]\n [IMAGE_DIRS <directory1> <directory2> ...]\n [IMAGES <image_file1> <image_file2>\n [CONFIGURE <tex_file> <tex_file> ...]\n [DEPENDS <tex_file> <tex_file> ...]\n [MULTIBIB_NEWCITES] <suffix_list>\n [USE_INDEX] [USE_GLOSSARY] [USE_NOMENCL]\n [DEFAULT_PDF] [DEFAULT_SAFEPDF] [DEFAULT_PS] [NO_DEFAULT]\n [MANGLE_TARGET_NAMES])"
+ )
+ENDFUNCTION(LATEX_USAGE command message)
+
+# Parses arguments to ADD_LATEX_DOCUMENT and ADD_LATEX_TARGETS and sets the
+# variables LATEX_TARGET, LATEX_IMAGE_DIR, LATEX_BIBFILES, LATEX_DEPENDS, and
+# LATEX_INPUTS.
+FUNCTION(PARSE_ADD_LATEX_ARGUMENTS command)
+ LATEX_PARSE_ARGUMENTS(
+ LATEX
+ "BIBFILES;FATHER_TARGET;MULTIBIB_NEWCITES;INPUTS;IMAGE_DIRS;IMAGES;CONFIGURE;DEPENDS"
+ "USE_INDEX;USE_GLOSSARY;USE_GLOSSARIES;USE_NOMENCL;DEFAULT_PDF;DEFAULT_SAFEPDF;DEFAULT_PS;NO_DEFAULT;MANGLE_TARGET_NAMES"
+ ${ARGN}
+ )
+
+ # The first argument is the target latex file.
+ IF (LATEX_DEFAULT_ARGS)
+ LIST(GET LATEX_DEFAULT_ARGS 0 latex_main_input)
+ LIST(REMOVE_AT LATEX_DEFAULT_ARGS 0)
+ LATEX_GET_FILENAME_COMPONENT(latex_target ${latex_main_input} NAME_WE)
+ SET(LATEX_MAIN_INPUT ${latex_main_input} CACHE INTERNAL "" FORCE)
+ SET(LATEX_TARGET ${latex_target} CACHE INTERNAL "" FORCE)
+ ELSE (LATEX_DEFAULT_ARGS)
+ LATEX_USAGE(${command} "No tex file target given to ${command}.")
+ ENDIF (LATEX_DEFAULT_ARGS)
+
+ IF (LATEX_DEFAULT_ARGS)
+ LATEX_USAGE(${command} "Invalid or depricated arguments: ${LATEX_DEFAULT_ARGS}")
+ ENDIF (LATEX_DEFAULT_ARGS)
+
+ # Backward compatibility between 1.6.0 and 1.6.1.
+ IF (LATEX_USE_GLOSSARIES)
+ SET(LATEX_USE_GLOSSARY TRUE CACHE INTERNAL "" FORCE)
+ ENDIF (LATEX_USE_GLOSSARIES)
+ENDFUNCTION(PARSE_ADD_LATEX_ARGUMENTS)
+
+FUNCTION(ADD_LATEX_TARGETS_INTERNAL)
+ IF (LATEX_USE_SYNCTEX)
+ SET(synctex_flags ${LATEX_SYNCTEX_FLAGS})
+ ELSE (LATEX_USE_SYNCTEX)
+ SET(synctex_flags)
+ ENDIF (LATEX_USE_SYNCTEX)
+
+ # The commands to run LaTeX. They are repeated multiple times.
+ SET(latex_build_command
+ ${LATEX_COMPILER} ${LATEX_COMPILER_FLAGS} ${synctex_flags} ${LATEX_MAIN_INPUT}
+ )
+ SET(pdflatex_build_command
+ ${PDFLATEX_COMPILER} ${PDFLATEX_COMPILER_FLAGS} ${synctex_flags} ${LATEX_MAIN_INPUT}
+ )
+
+ # Set up target names.
+ IF (LATEX_MANGLE_TARGET_NAMES)
+ SET(dvi_target ${LATEX_TARGET}_dvi)
+ SET(pdf_target ${LATEX_TARGET}_pdf)
+ SET(ps_target ${LATEX_TARGET}_ps)
+ SET(safepdf_target ${LATEX_TARGET}_safepdf)
+ SET(html_target ${LATEX_TARGET}_html)
+ SET(auxclean_target ${LATEX_TARGET}_auxclean)
+ ELSE (LATEX_MANGLE_TARGET_NAMES)
+ SET(dvi_target dvi)
+ SET(pdf_target pdf)
+ SET(ps_target ps)
+ SET(safepdf_target safepdf)
+ SET(html_target html)
+ SET(auxclean_target auxclean)
+ ENDIF (LATEX_MANGLE_TARGET_NAMES)
+
+ # Probably not all of these will be generated, but they could be.
+ # Note that the aux file is added later.
+ SET(auxiliary_clean_files
+ ${output_dir}/${LATEX_TARGET}.aux
+ ${output_dir}/${LATEX_TARGET}.bbl
+ ${output_dir}/${LATEX_TARGET}.blg
+ ${output_dir}/${LATEX_TARGET}-blx.bib
+ ${output_dir}/${LATEX_TARGET}.glg
+ ${output_dir}/${LATEX_TARGET}.glo
+ ${output_dir}/${LATEX_TARGET}.gls
+ ${output_dir}/${LATEX_TARGET}.idx
+ ${output_dir}/${LATEX_TARGET}.ilg
+ ${output_dir}/${LATEX_TARGET}.ind
+ ${output_dir}/${LATEX_TARGET}.ist
+ ${output_dir}/${LATEX_TARGET}.log
+ ${output_dir}/${LATEX_TARGET}.out
+ ${output_dir}/${LATEX_TARGET}.toc
+ ${output_dir}/${LATEX_TARGET}.lof
+ ${output_dir}/${LATEX_TARGET}.xdy
+ ${output_dir}/${LATEX_TARGET}.synctex.gz
+ ${output_dir}/${LATEX_TARGET}.synctex.bak.gz
+ ${output_dir}/${LATEX_TARGET}.dvi
+ ${output_dir}/${LATEX_TARGET}.ps
+ ${output_dir}/${LATEX_TARGET}.pdf
+ )
+
+ SET(image_list ${LATEX_IMAGES})
+
+ # For each directory in LATEX_IMAGE_DIRS, glob all the image files and
+ # place them in LATEX_IMAGES.
+ FOREACH(dir ${LATEX_IMAGE_DIRS})
+ IF (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${dir})
+ MESSAGE(WARNING "Image directory ${CMAKE_CURRENT_SOURCE_DIR}/${dir} does not exist. Are you sure you gave relative directories to IMAGE_DIRS?")
+ ENDIF (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${dir})
+ FOREACH(extension ${LATEX_IMAGE_EXTENSIONS})
+ FILE(GLOB files ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*${extension})
+ FOREACH(file ${files})
+ LATEX_GET_FILENAME_COMPONENT(filename ${file} NAME)
+ SET(image_list ${image_list} ${dir}/${filename})
+ ENDFOREACH(file)
+ ENDFOREACH(extension)
+ ENDFOREACH(dir)
+
+ LATEX_PROCESS_IMAGES(dvi_images pdf_images ${image_list})
+
+ SET(make_dvi_command
+ ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${latex_build_command})
+ SET(make_pdf_command
+ ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${pdflatex_build_command}
+ )
+
+ SET(make_dvi_depends ${LATEX_DEPENDS} ${dvi_images})
+ SET(make_pdf_depends ${LATEX_DEPENDS} ${pdf_images})
+ FOREACH(input ${LATEX_MAIN_INPUT} ${LATEX_INPUTS})
+ SET(make_dvi_depends ${make_dvi_depends} ${output_dir}/${input})
+ SET(make_pdf_depends ${make_pdf_depends} ${output_dir}/${input})
+ IF (${input} MATCHES "\\.tex$")
+ # Dependent .tex files might have their own .aux files created. Make
+ # sure these get cleaned as well. This might replicate the cleaning
+ # of the main .aux file, which is OK.
+ STRING(REGEX REPLACE "\\.tex$" "" input_we ${input})
+ SET(auxiliary_clean_files ${auxiliary_clean_files}
+ ${output_dir}/${input_we}.aux
+ ${output_dir}/${input}.aux
+ )
+ ENDIF (${input} MATCHES "\\.tex$")
+ ENDFOREACH(input)
+
+ IF (LATEX_USE_GLOSSARY)
+ FOREACH(dummy 0 1) # Repeat these commands twice.
+ SET(make_dvi_command ${make_dvi_command}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${CMAKE_COMMAND}
+ -D LATEX_BUILD_COMMAND=makeglossaries
+ -D LATEX_TARGET=${LATEX_TARGET}
+ -D MAKEINDEX_COMPILER=${MAKEINDEX_COMPILER}
+ -D XINDY_COMPILER=${XINDY_COMPILER}
+ -D MAKEGLOSSARIES_COMPILER_FLAGS=${MAKEGLOSSARIES_COMPILER_FLAGS}
+ -P ${LATEX_USE_LATEX_LOCATION}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${latex_build_command}
+ )
+ SET(make_pdf_command ${make_pdf_command}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${CMAKE_COMMAND}
+ -D LATEX_BUILD_COMMAND=makeglossaries
+ -D LATEX_TARGET=${LATEX_TARGET}
+ -D MAKEINDEX_COMPILER=${MAKEINDEX_COMPILER}
+ -D XINDY_COMPILER=${XINDY_COMPILER}
+ -D MAKEGLOSSARIES_COMPILER_FLAGS=${MAKEGLOSSARIES_COMPILER_FLAGS}
+ -P ${LATEX_USE_LATEX_LOCATION}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${pdflatex_build_command}
+ )
+ ENDFOREACH(dummy)
+ ENDIF (LATEX_USE_GLOSSARY)
+
+ IF (LATEX_USE_NOMENCL)
+ FOREACH(dummy 0 1) # Repeat these commands twice.
+ SET(make_dvi_command ${make_dvi_command}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${CMAKE_COMMAND}
+ -D LATEX_BUILD_COMMAND=makenomenclature
+ -D LATEX_TARGET=${LATEX_TARGET}
+ -D MAKEINDEX_COMPILER=${MAKEINDEX_COMPILER}
+ -D MAKENOMENCLATURE_COMPILER_FLAGS=${MAKENOMENCLATURE_COMPILER_FLAGS}
+ -P ${LATEX_USE_LATEX_LOCATION}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${latex_build_command}
+ )
+ SET(make_pdf_command ${make_pdf_command}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${CMAKE_COMMAND}
+ -D LATEX_BUILD_COMMAND=makenomenclature
+ -D LATEX_TARGET=${LATEX_TARGET}
+ -D MAKEINDEX_COMPILER=${MAKEINDEX_COMPILER}
+ -D MAKENOMENCLATURE_COMPILER_FLAGS=${MAKENOMENCLATURE_COMPILER_FLAGS}
+ -P ${LATEX_USE_LATEX_LOCATION}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${pdflatex_build_command}
+ )
+ ENDFOREACH(dummy)
+ ENDIF (LATEX_USE_NOMENCL)
+
+ IF (LATEX_BIBFILES)
+ IF (LATEX_MULTIBIB_NEWCITES)
+ FOREACH (multibib_auxfile ${LATEX_MULTIBIB_NEWCITES})
+ LATEX_GET_FILENAME_COMPONENT(multibib_target ${multibib_auxfile} NAME_WE)
+ SET(make_dvi_command ${make_dvi_command}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${BIBTEX_COMPILER} ${BIBTEX_COMPILER_FLAGS} ${multibib_target})
+ SET(make_pdf_command ${make_pdf_command}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${BIBTEX_COMPILER} ${BIBTEX_COMPILER_FLAGS} ${multibib_target})
+ SET(auxiliary_clean_files ${auxiliary_clean_files}
+ ${output_dir}/${multibib_target}.aux)
+ ENDFOREACH (multibib_auxfile ${LATEX_MULTIBIB_NEWCITES})
+ ELSE (LATEX_MULTIBIB_NEWCITES)
+ SET(make_dvi_command ${make_dvi_command}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${BIBTEX_COMPILER} ${BIBTEX_COMPILER_FLAGS} ${LATEX_TARGET})
+ SET(make_pdf_command ${make_pdf_command}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${BIBTEX_COMPILER} ${BIBTEX_COMPILER_FLAGS} ${LATEX_TARGET})
+ ENDIF (LATEX_MULTIBIB_NEWCITES)
+
+ FOREACH (bibfile ${LATEX_BIBFILES})
+ SET(make_dvi_depends ${make_dvi_depends} ${output_dir}/${bibfile})
+ SET(make_pdf_depends ${make_pdf_depends} ${output_dir}/${bibfile})
+ ENDFOREACH (bibfile ${LATEX_BIBFILES})
+ ELSE (LATEX_BIBFILES)
+ IF (LATEX_MULTIBIB_NEWCITES)
+ MESSAGE(WARNING "MULTIBIB_NEWCITES has no effect without BIBFILES option.")
+ ENDIF (LATEX_MULTIBIB_NEWCITES)
+ ENDIF (LATEX_BIBFILES)
+
+ IF (LATEX_USE_INDEX)
+ SET(make_dvi_command ${make_dvi_command}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${latex_build_command}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${MAKEINDEX_COMPILER} ${MAKEINDEX_COMPILER_FLAGS} ${LATEX_TARGET}.idx)
+ SET(make_pdf_command ${make_pdf_command}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${pdflatex_build_command}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${MAKEINDEX_COMPILER} ${MAKEINDEX_COMPILER_FLAGS} ${LATEX_TARGET}.idx)
+ ENDIF (LATEX_USE_INDEX)
+
+ SET(make_dvi_command ${make_dvi_command}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${latex_build_command}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${latex_build_command})
+ SET(make_pdf_command ${make_pdf_command}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${pdflatex_build_command}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${pdflatex_build_command})
+
+ IF (LATEX_USE_SYNCTEX)
+ IF (NOT GZIP)
+ MESSAGE(SEND_ERROR "UseLATEX.cmake: USE_SYNTEX option requires gzip program. Set GZIP variable.")
+ ENDIF (NOT GZIP)
+ SET(make_dvi_command ${make_dvi_command}
+ COMMAND ${CMAKE_COMMAND}
+ -D LATEX_BUILD_COMMAND=correct_synctex
+ -D LATEX_TARGET=${LATEX_TARGET}
+ -D GZIP=${GZIP}
+ -D "LATEX_SOURCE_DIRECTORY=${CMAKE_CURRENT_SOURCE_DIR}"
+ -D "LATEX_BINARY_DIRECTORY=${output_dir}"
+ -P ${LATEX_USE_LATEX_LOCATION}
+ )
+ SET(make_pdf_command ${make_pdf_command}
+ COMMAND ${CMAKE_COMMAND}
+ -D LATEX_BUILD_COMMAND=correct_synctex
+ -D LATEX_TARGET=${LATEX_TARGET}
+ -D GZIP=${GZIP}
+ -D "LATEX_SOURCE_DIRECTORY=${CMAKE_CURRENT_SOURCE_DIR}"
+ -D "LATEX_BINARY_DIRECTORY=${output_dir}"
+ -P ${LATEX_USE_LATEX_LOCATION}
+ )
+ ENDIF (LATEX_USE_SYNCTEX)
+
+ # Add commands and targets for building dvi outputs.
+ ADD_CUSTOM_COMMAND(OUTPUT ${output_dir}/${LATEX_TARGET}.dvi
+ COMMAND ${make_dvi_command}
+ DEPENDS ${make_dvi_depends}
+ )
+ IF (LATEX_NO_DEFAULT OR LATEX_DEFAULT_PDF OR LATEX_DEFAULT_SAFEPDF OR DEFAULT_PS)
+ ADD_CUSTOM_TARGET(${dvi_target}
+ DEPENDS ${output_dir}/${LATEX_TARGET}.dvi)
+ ELSE (LATEX_NO_DEFAULT OR LATEX_DEFAULT_PDF OR LATEX_DEFAULT_SAFEPDF OR DEFAULT_PS)
+ IF (LATEX_FATHER_TARGET)
+ ADD_CUSTOM_TARGET(${dvi_target}
+ DEPENDS ${output_dir}/${LATEX_TARGET}.dvi)
+ ADD_DEPENDENCIES(${LATEX_FATHER_TARGET} ${dvi_target})
+ ELSE (LATEX_FATHER_TARGET)
+ ADD_CUSTOM_TARGET(${dvi_target} ALL
+ DEPENDS ${output_dir}/${LATEX_TARGET}.dvi)
+ ENDIF (LATEX_FATHER_TARGET)
+ ENDIF (LATEX_NO_DEFAULT OR LATEX_DEFAULT_PDF OR LATEX_DEFAULT_SAFEPDF OR DEFAULT_PS)
+
+ # Add commands and targets for building pdf outputs (with pdflatex).
+ IF (PDFLATEX_COMPILER)
+ ADD_CUSTOM_COMMAND(OUTPUT ${output_dir}/${LATEX_TARGET}.pdf
+ COMMAND ${make_pdf_command}
+ DEPENDS ${make_pdf_depends}
+ )
+ IF (LATEX_DEFAULT_PDF)
+ IF (LATEX_FATHER_TARGET)
+ ADD_CUSTOM_TARGET(${pdf_target}
+ DEPENDS ${output_dir}/${LATEX_TARGET}.pdf)
+ ADD_DEPENDENCIES(${LATEX_FATHER_TARGET} ${pdf_target})
+ ELSE (LATEX_FATHER_TARGET)
+ ADD_CUSTOM_TARGET(${pdf_target} ALL
+ DEPENDS ${output_dir}/${LATEX_TARGET}.pdf)
+ ENDIF (LATEX_FATHER_TARGET)
+ ELSE (LATEX_DEFAULT_PDF)
+ ADD_CUSTOM_TARGET(${pdf_target}
+ DEPENDS ${output_dir}/${LATEX_TARGET}.pdf)
+ ENDIF (LATEX_DEFAULT_PDF)
+ ENDIF (PDFLATEX_COMPILER)
+
+ IF (DVIPS_CONVERTER)
+ ADD_CUSTOM_COMMAND(OUTPUT ${output_dir}/${LATEX_TARGET}.ps
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${DVIPS_CONVERTER} ${DVIPS_CONVERTER_FLAGS} -o ${LATEX_TARGET}.ps ${LATEX_TARGET}.dvi
+ DEPENDS ${output_dir}/${LATEX_TARGET}.dvi)
+ IF (LATEX_DEFAULT_PS)
+ ADD_CUSTOM_TARGET(${ps_target} ALL
+ DEPENDS ${output_dir}/${LATEX_TARGET}.ps)
+ ELSE (LATEX_DEFAULT_PS)
+ ADD_CUSTOM_TARGET(${ps_target}
+ DEPENDS ${output_dir}/${LATEX_TARGET}.ps)
+ ENDIF (LATEX_DEFAULT_PS)
+ IF (PS2PDF_CONVERTER)
+ # Since both the pdf and safepdf targets have the same output, we
+ # cannot properly do the dependencies for both. When selecting safepdf,
+ # simply force a recompile every time.
+ IF (LATEX_DEFAULT_SAFEPDF)
+ IF (LATEX_FATHER_TARGET)
+ ADD_CUSTOM_TARGET(${safepdf_target}
+ ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${PS2PDF_CONVERTER} ${PS2PDF_CONVERTER_FLAGS} ${LATEX_TARGET}.ps ${LATEX_TARGET}.pdf
+ )
+ ADD_DEPENDENCIES(${LATEX_FATHER_TARGET} ${safepdf_target})
+ ELSE (LATEX_FATHER_TARGET)
+ ADD_CUSTOM_TARGET(${safepdf_target} ALL
+ ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${PS2PDF_CONVERTER} ${PS2PDF_CONVERTER_FLAGS} ${LATEX_TARGET}.ps ${LATEX_TARGET}.pdf
+ )
+ ENDIF (LATEX_FATHER_TARGET)
+ ELSE (LATEX_DEFAULT_SAFEPDF)
+ ADD_CUSTOM_TARGET(${safepdf_target}
+ ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${PS2PDF_CONVERTER} ${PS2PDF_CONVERTER_FLAGS} ${LATEX_TARGET}.ps ${LATEX_TARGET}.pdf
+ )
+ ENDIF (LATEX_DEFAULT_SAFEPDF)
+ ADD_DEPENDENCIES(${safepdf_target} ${ps_target})
+ ENDIF (PS2PDF_CONVERTER)
+ ENDIF (DVIPS_CONVERTER)
+
+ IF (LATEX2HTML_CONVERTER)
+ IF (USING_HTLATEX)
+ # htlatex places the output in a different location
+ SET (HTML_OUTPUT "${output_dir}/${LATEX_TARGET}.html")
+ ELSE (USING_HTLATEX)
+ SET (HTML_OUTPUT "${output_dir}/${LATEX_TARGET}/${LATEX_TARGET}.html")
+ ENDIF (USING_HTLATEX)
+ ADD_CUSTOM_COMMAND(OUTPUT ${HTML_OUTPUT}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir}
+ ${LATEX2HTML_CONVERTER} ${LATEX2HTML_CONVERTER_FLAGS} ${LATEX_MAIN_INPUT}
+ DEPENDS ${output_dir}/${LATEX_TARGET}.tex
+ )
+ ADD_CUSTOM_TARGET(${html_target}
+ DEPENDS ${HTML_OUTPUT}
+ )
+ ADD_DEPENDENCIES(${html_target} ${dvi_target})
+ ENDIF (LATEX2HTML_CONVERTER)
+
+ SET_DIRECTORY_PROPERTIES(.
+ ADDITIONAL_MAKE_CLEAN_FILES "${auxiliary_clean_files}"
+ )
+
+ ADD_CUSTOM_TARGET(${auxclean_target}
+ COMMENT "Cleaning auxiliary LaTeX files."
+ COMMAND ${CMAKE_COMMAND} -E remove ${auxiliary_clean_files}
+ )
+ENDFUNCTION(ADD_LATEX_TARGETS_INTERNAL)
+
+FUNCTION(ADD_LATEX_TARGETS)
+ LATEX_GET_OUTPUT_PATH(output_dir)
+ PARSE_ADD_LATEX_ARGUMENTS(ADD_LATEX_TARGETS ${ARGV})
+
+ ADD_LATEX_TARGETS_INTERNAL()
+ENDFUNCTION(ADD_LATEX_TARGETS)
+
+FUNCTION(ADD_LATEX_DOCUMENT)
+ LATEX_GET_OUTPUT_PATH(output_dir)
+ IF (output_dir)
+ PARSE_ADD_LATEX_ARGUMENTS(ADD_LATEX_DOCUMENT ${ARGV})
+
+ LATEX_COPY_INPUT_FILE(${LATEX_MAIN_INPUT})
+
+ FOREACH (bib_file ${LATEX_BIBFILES})
+ LATEX_COPY_INPUT_FILE(${bib_file})
+ ENDFOREACH (bib_file)
+
+ FOREACH (input ${LATEX_INPUTS})
+ LATEX_COPY_INPUT_FILE(${input})
+ ENDFOREACH(input)
+
+ LATEX_COPY_GLOBBED_FILES(${CMAKE_CURRENT_SOURCE_DIR}/*.cls ${output_dir})
+ LATEX_COPY_GLOBBED_FILES(${CMAKE_CURRENT_SOURCE_DIR}/*.bst ${output_dir})
+ LATEX_COPY_GLOBBED_FILES(${CMAKE_CURRENT_SOURCE_DIR}/*.clo ${output_dir})
+ LATEX_COPY_GLOBBED_FILES(${CMAKE_CURRENT_SOURCE_DIR}/*.sty ${output_dir})
+ LATEX_COPY_GLOBBED_FILES(${CMAKE_CURRENT_SOURCE_DIR}/*.ist ${output_dir})
+ LATEX_COPY_GLOBBED_FILES(${CMAKE_CURRENT_SOURCE_DIR}/*.fd ${output_dir})
+
+ ADD_LATEX_TARGETS_INTERNAL()
+ ENDIF (output_dir)
+ENDFUNCTION(ADD_LATEX_DOCUMENT)
+
+#############################################################################
+# Actually do stuff
+#############################################################################
+
+IF (LATEX_BUILD_COMMAND)
+ SET(command_handled)
+
+ IF ("${LATEX_BUILD_COMMAND}" STREQUAL makeglossaries)
+ LATEX_MAKEGLOSSARIES()
+ SET(command_handled TRUE)
+ ENDIF ("${LATEX_BUILD_COMMAND}" STREQUAL makeglossaries)
+
+ IF ("${LATEX_BUILD_COMMAND}" STREQUAL makenomenclature)
+ LATEX_MAKENOMENCLATURE()
+ SET(command_handled TRUE)
+ ENDIF ("${LATEX_BUILD_COMMAND}" STREQUAL makenomenclature)
+
+ IF ("${LATEX_BUILD_COMMAND}" STREQUAL correct_synctex)
+ LATEX_CORRECT_SYNCTEX()
+ SET(command_handled TRUE)
+ ENDIF ("${LATEX_BUILD_COMMAND}" STREQUAL correct_synctex)
+
+ IF (NOT command_handled)
+ MESSAGE(SEND_ERROR "Unknown command: ${LATEX_BUILD_COMMAND}")
+ ENDIF (NOT command_handled)
+
+ELSE (LATEX_BUILD_COMMAND)
+ # Must be part of the actual configure (included from CMakeLists.txt).
+ LATEX_SETUP_VARIABLES()
+ENDIF (LATEX_BUILD_COMMAND)
--- /dev/null
+Makefile.in
+Makefile
--- /dev/null
+EXTRA_DIST = dune-common-config.cmake.in
+
+include $(top_srcdir)/am/global-rules
--- /dev/null
+if(NOT @DUNE_MOD_NAME@_FOUND)
+@PACKAGE_INIT@
+
+#import the target
+get_filename_component(_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
+include("${_dir}/@DUNE_MOD_NAME@-targets.cmake")
+
+#report other information
+set_and_check(@DUNE_MOD_NAME@_PREFIX "${PACKAGE_PREFIX_DIR}")
+set_and_check(@DUNE_MOD_NAME@_INCLUDE_DIRS "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@")
+set(@DUNE_MOD_NAME@_CXX_FLAGS "@CMAKE_CXX_FLAGS@")
+set(@DUNE_MOD_NAME@_CXX_FLAGS_DEBUG "@CMAKE_CXX_FLAGS_DEBUG@")
+set(@DUNE_MOD_NAME@_CXX_FLAGS_MINSIZEREL "@CMAKE_CXX_FLAGS_MINSIZEREL@")
+set(@DUNE_MOD_NAME@_CXX_FLAGS_RELEASE "@CMAKE_CXX_FLAGS_RELEASE@")
+set(@DUNE_MOD_NAME@_CXX_FLAGS_RELWITHDEBINFO "@CMAKE_CXX_FLAGS_RELWITHDEBINFO@")
+set(@DUNE_MOD_NAME@_LIBRARIES "dunecommon")
+set_and_check(@DUNE_MOD_NAME@_SCRIPT_DIR "@PACKAGE_SCRIPT_DIR@")
+set_and_check(DOXYSTYLE_FILE "@PACKAGE_DOXYSTYLE_DIR@/Doxystyle")
+set(@DUNE_MOD_NAME@_DEPENDS "@DUNE_DEPENDS@")
+set(@DUNE_MOD_NAME@_SUGGESTS "@DUNE_SUGGESTS@")
+set_and_check(@DUNE_MOD_NAME@_MODULE_PATH "@PACKAGE_DUNE_INSTALL_MODULEDIR@")
+endif(NOT @DUNE_MOD_NAME@_FOUND)
--- /dev/null
+Makefile.in
+Makefile
--- /dev/null
+MACRO(get_directory_test_target _target _dir)
+ string(REPLACE "@CMAKE_BINARY_DIR@" "" _relative_dir "${_dir}")
+ string(REPLACE "/" "_" ${_target} "${_relative_dir}")
+ENDMACRO(get_directory_test_target _target _dir)
+
+get_directory_test_target(_build_test_target "@CMAKE_CURRENT_BINARY_DIR@")
+execute_process(COMMAND @CMAKE_COMMAND@ --build @CMAKE_BINARY_DIR@
+ --target ${_build_test_target})
--- /dev/null
+set(modules
+ CreateDoxyFile.cmake
+ FinalizeHeadercheck.cmake
+ FindFiles.cmake
+ InstallFile.cmake
+ RunDoxygen.cmake)
+
+install(FILES ${modules} ${CMAKE_CURRENT_SOURCE_DIR}/BuildTests.cmake.in
+ DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/dune/cmake/scripts)
--- /dev/null
+#For now we just support appending Doxyfile and Doxylocal
+message(STATUS "Generating Doxyfile.in")
+FILE(READ ${DOXYSTYLE} file_contents)
+FILE(WRITE Doxyfile.in ${file_contents})
+FILE(READ ${DOXYLOCAL} file_contents)
+FILE(APPEND Doxyfile.in ${file_contents})
+
+# configure_file does not work as it insists an existing input file, which in our
+# needs to be generated first.
+# Therfore we read the Doxyfile.in and replace the variables using STRING(CONFIGURE)
+# and the write the file.
+FILE(READ Doxyfile.in file_contents)
+STRING(CONFIGURE ${file_contents} output)
+FILE(WRITE Doxyfile ${output})
--- /dev/null
+# this is script is called at the end of all header checks
+message("Headerchecks finished! Rerun CMake if a new file has not been checked!")
+
+#message("Running make clean on headercheck targets...")
+#this cleans the build directory from pollution through headerchecks but prevents caching... :/
+#file(GLOB_RECURSE list "./CMakeFiles/headercheck_*/cmake_clean.cmake")
+#foreach(item ${list})
+ # execute_process(COMMAND ${CMAKE_COMMAND} -P ${item})
+#endforeach()
\ No newline at end of file
--- /dev/null
+#Do not follow symlinks during FILE GLOB_RECURSE
+cmake_policy(SET CMP0009 NEW)
+file(GLOB_RECURSE makefiles RELATIVE ${RELPATH} "CMakeLists.txt")
+foreach(_file ${makefiles})
+ # path contains "/test" or is directly "test"
+ string(REGEX MATCH "(.*/)*test" _testdir ${_file})
+ # path end with "/test" and not "/testFoo" or "/test/foo"
+ string(REGEX MATCH "(.*/)*test/CMakeLists.txt$" _testdirensured ${_file})
+ if(_testdir AND _testdirensured)
+ list(APPEND _makefiles ${_testdir})
+ endif(_testdir AND _testdirensured)
+endforeach(_file ${makefiles})
+if(_makefiles)
+ message("${_makefiles}")
+endif(_makefiles)
--- /dev/null
+
+# Somehow variable list get destroyed when calling cmake (; is replaced with
+# whitespace character. Undo this change
+string(REGEX REPLACE "([a-zA-Z0-9]) ([/a-zA-Z0-9])" "\\1;\\2" files "${FILES}")
+file(INSTALL ${files} DESTINATION ${DIR})
+
--- /dev/null
+MODULES = BuildTests.cmake.in \
+ CreateDoxyFile.cmake \
+ FinalizeHeadercheck.cmake \
+ FindFiles.cmake \
+ InstallFile.cmake \
+ RunDoxygen.cmake
+
+modulesdir = $(datadir)/dune/cmake/scripts
+dist_modules_DATA = ${MODULES}
+
+include $(top_srcdir)/am/global-rules
+EXTRA_DIST = CMakeLists.txt
--- /dev/null
+execute_process(COMMAND
+ ${DOXYGEN_EXECUTABLE} Doxyfile OUTPUT_FILE doxygen.log ERROR_FILE doxygen.log
+ TIMEOUT 120)
--- /dev/null
+/* config.h. Generated from config.h.cmake by CMake. */
+
+/* begin dune-common */
+
+#ifdef DEPRECATED_MPI_CPPFLAGS_USED
+#warning The MPI_CPPFLAGS configure substitute is deprecated. Please change
+#warning your Makefile.am to use DUNEMPICPPFLAGS instead. Note that it is a
+#warning good idea to change any occurance of MPI_LDFLAGS into DUNEMPILIBS and
+#warning DUNEMPILDFLAGS as appropriate, since it is not possible to issue a
+#warning deprecation warning in that case.
+#endif
+
+/* Define to the version of dune-common */
+#define DUNE_COMMON_VERSION "${DUNE_COMMON_VERSION}"
+
+/* Define to the major version of dune-common */
+#define DUNE_COMMON_VERSION_MAJOR ${DUNE_COMMON_VERSION_MAJOR}
+
+/* Define to the minor version of dune-common */
+#define DUNE_COMMON_VERSION_MINOR ${DUNE_COMMON_VERSION_MINOR}
+
+/* Define to the revision of dune-common */
+#define DUNE_COMMON_VERSION_REVISION ${DUNE_COMMON_VERSION_REVISION}
+
+/* Standard debug streams with a level below will collapse to doing nothing */
+#define DUNE_MINIMAL_DEBUG_LEVEL ${DUNE_MINIMAL_DEBUG_LEVEL}
+
+/* does the compiler support __attribute__((deprecated))? */
+#cmakedefine HAS_ATTRIBUTE_DEPRECATED 1
+
+/* does the compiler support __attribute__((deprecated("message"))? */
+#cmakedefine HAS_ATTRIBUTE_DEPRECATED_MSG 1
+
+/* does the compiler support __attribute__((unused))? */
+#cmakedefine HAS_ATTRIBUTE_UNUSED 1
+
+/* Define to 1 if the <array> C++11 is available and support array::fill */
+#cmakedefine HAVE_ARRAY 1
+
+/* Define if you have a BLAS library. */
+#cmakedefine HAVE_BLAS 1
+
+/* Define to ENABLE_BOOST if the Boost library is available */
+#cmakedefine HAVE_DUNE_BOOST ENABLE_BOOST
+
+/* Define to 1 if you have <boost/make_shared.hpp>. */
+#cmakedefine HAVE_BOOST_MAKE_SHARED_HPP 1
+
+/* Define to 1 if you have the <boost/shared_ptr.hpp> header file. */
+#cmakedefine HAVE_BOOST_SHARED_PTR_HPP 1
+
+/* does the compiler support abi::__cxa_demangle */
+#cmakedefine HAVE_CXA_DEMANGLE 1
+
+/* Define if you have LAPACK library. */
+#cmakedefine HAVE_LAPACK 1
+
+/* Define to 1 if SHARED_PTR_NAMESPACE::make_shared is usable. */
+#cmakedefine HAVE_MAKE_SHARED 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+// Not used! #cmakedefine01 HAVE_MALLOC_H
+
+/* Define if you have the MPI library. This is only true if MPI was found by
+ configure _and_ if the application uses the DUNEMPICPPFLAGS (or the
+ deprecated MPI_CPPFLAGS) */
+#cmakedefine HAVE_MPI ENABLE_MPI
+
+/* Define if you have the GNU GMP library. The value should be ENABLE_GMP
+ to facilitate activating and deactivating GMP using compile flags. */
+#cmakedefine HAVE_GMP ENABLE_GMP
+
+/* Define to 1 if you have the symbol mprotect. */
+#cmakedefine HAVE_MPROTECT 1
+
+/* Define to 1 if nullptr is supported */
+#cmakedefine HAVE_NULLPTR 1
+
+/* Define to 1 if static_assert is supported */
+#cmakedefine HAVE_STATIC_ASSERT 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#cmakedefine HAVE_STDINT_H 1
+
+/* Define to 1 if you have <sys/mman.h>. */
+#cmakedefine HAVE_SYS_MMAN_H 1
+
+/* Define to 1 if the std::tr1::hash template from TR1 is available. */
+#cmakedefine HAVE_TR1_HASH 1
+
+/* Define to 1 if you have the <tr1/tuple> header file. */
+#cmakedefine HAVE_TR1_TUPLE 1
+
+/* Define to 1 if you have the <tr1/type_traits> header file. */
+#cmakedefine HAVE_TR1_TYPE_TRAITS 1
+
+/* Define to 1 if std::integral_constant< T, v > is supported
+ * and casts into T
+ */
+#cmakedefine HAVE_INTEGRAL_CONSTANT 1
+
+/* Define to 1 if the std::hash template from C++11 is available. */
+#cmakedefine HAVE_STD_HASH 1
+
+/* Define to 1 if you have the <tuple> header file. */
+#cmakedefine HAVE_TUPLE 1
+
+/* Define to 1 if you have the <type_traits> header file. */
+#cmakedefine HAVE_TYPE_TRAITS 1
+
+/* Define to 1 if you have the <type_traits> header file. */
+#cmakedefine HAVE_STD_CONDITIONAL 1
+
+/* Define to 1 if the MPI2 Standard is supported */
+#cmakedefine MPI_2 1
+
+/* begin private */
+
+/* Name of package */
+#define PACKAGE "dune-common"
+
+/* 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@"
+
+/* Version number of package */
+#define VERSION "@DUNE_MOD_VERSION@"
+
+/* end private */
+
+/* The header in which SHARED_PTR can be found */
+#cmakedefine SHARED_PTR_HEADER ${SHARED_PTR_HEADER}
+
+/* The namespace in which SHARED_PTR can be found */
+#cmakedefine SHARED_PTR_NAMESPACE ${SHARED_PTR_NAMESPACE}
+
+/* Define to 1 if variadic templates are supported */
+#cmakedefine HAVE_VARIADIC_TEMPLATES 1
+
+/* Define to 1 if SFINAE on variadic template constructors is fully supported */
+#cmakedefine HAVE_VARIADIC_CONSTRUCTOR_SFINAE 1
+
+/* Define to 1 if rvalue references are supported */
+#cmakedefine HAVE_RVALUE_REFERENCES 1
+
+/* Define to 1 if initializer list is supported */
+#cmakedefine HAVE_INITIALIZER_LIST 1
+
+/* Define to if the UMFPack library is available */
+#cmakedefine HAVE_UMFPACK ENABLE_UMFPACK
+
+/* Include always useful headers */
+#include <dune/common/deprecated.hh>
+#include <dune/common/unused.hh>
+#include "FC.h"
+#define FC_FUNC FC_GLOBAL_
+
+/* end dune-common */
--- /dev/null
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ([2.62])
+DUNE_AC_INIT # gets module version from dune.module file
+AC_CONFIG_SRCDIR([dune/common/stdstreams.cc])
+AC_CONFIG_HEADERS([config.h])
+
+# add configure flags needed to create log files for dune-autobuild
+DUNE_AUTOBUILD_FLAGS
+# check all dune dependecies and prerequisits
+DUNE_CHECK_ALL
+
+# preset variable to path such that #include <dune/...> works
+AC_SUBST([DUNE_COMMON_ROOT], '$(abs_top_srcdir)')
+AC_SUBST([DUNE_COMMON_BIN], '$(abs_top_srcdir)/bin/')
+AC_SUBST([AM_CPPFLAGS], '-I$(top_srcdir)')
+AC_SUBST([AM_LDFLAGS], '$(DUNE_LDFLAGS)')
+AC_SUBST([LDADD], '$(top_builddir)/lib/libdunecommon.la')
+
+# write output
+AC_CONFIG_FILES([Makefile
+ lib/Makefile
+ bin/Makefile
+ cmake/Makefile
+ cmake/modules/Makefile
+ cmake/scripts/Makefile
+ cmake/pkg/Makefile
+ dune/Makefile
+ dune/common/Makefile
+ dune/common/test/Makefile
+ dune/common/parallel/Makefile
+ dune/common/parallel/test/Makefile
+ dune/common/std/Makefile
+ doc/Makefile
+ doc/comm/Makefile
+ doc/comm/figures/Makefile
+ doc/doxygen/Makefile
+ doc/doxygen/Doxyfile
+ doc/buildsystem/Makefile
+ m4/Makefile
+ am/Makefile
+ share/Makefile
+ share/bash-completion/Makefile
+ share/bash-completion/completions/Makefile
+ dune-common.pc])
+# make scripts executable
+AC_CONFIG_FILES([
+ bin/check-log-store],[
+ chmod +x bin/check-log-store])
+AC_OUTPUT
+
+# print results
+DUNE_SUMMARY_ALL
--- /dev/null
+.deps
+Makefile
+Makefile.in
+semantic.cache
--- /dev/null
+add_subdirectory("doxygen")
+add_subdirectory("buildsystem")
+add_subdirectory("comm")
+install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/example.opts
+ DESTINATION ${CMAKE_INSTALL_DOCDIR})
+install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dunecontrol.1
+ DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
--- /dev/null
+# $Id$
+
+# also build these sub directories
+SUBDIRS = doxygen buildsystem comm
+
+# setting like in dune-web
+CURDIR=doc
+# position of the web base directory,
+# relative to $(CURDIR)
+BASEDIR=..
+EXTRAINSTALL=example.opts
+
+# install the html pages
+DOCFILES = $(PAGES)
+DOCFILES_EXTRA = example.opts
+
+EXTRA_DIST = CMakeLists.txt $(PAGES) example.opts
+
+dist_man_MANS = dunecontrol.1
+
+# include rules for wml -> html transformation
+include $(top_srcdir)/am/webstuff
+
+# include further rules needed by Dune
+include $(top_srcdir)/am/global-rules
--- /dev/null
+*.aux
+*.log
+*.dvi
+*.ps
+*.pdf
+*.toc
+*.out
+*.ind
+*.ilg
+*.backup
+Makefile.in
+Makefile
+auto
--- /dev/null
+dune_add_latex_document(buildsystem.tex FATHER_TARGET doc DEFAULT_PDF INPUTS ../Makefile.am ../../configure.ac ../example.opts)
+create_doc_install(${CMAKE_CURRENT_BINARY_DIR}/buildsystem.pdf ${CMAKE_INSTALL_DOCDIR}/buildsystem)
--- /dev/null
+# $Id: Makefile.am 4499 2006-04-13 14:56:35Z christi $
+
+# setting like in dune-web
+CURDIR=doc/buildsystem
+BASEDIR=../..
+
+# install the html pages
+docdir=$(datadir)/doc/dune-common/buildsystem
+if BUILD_DOCS
+ DOCFILES=buildsystem.pdf
+ EXTRA_DIST= CMakeLists.txt $(DOCFILES)
+ EXTRAINSTALL=$(DOCFILES)
+endif
+
+# include predefined rules
+include $(top_srcdir)/am/webstuff
+include $(top_srcdir)/am/latex
+include $(top_srcdir)/am/global-rules
--- /dev/null
+\documentclass[11pt,a4paper,headinclude,footinclude,DIV16,normalheadings]{scrartcl}
+%\usepackage[today,nofancy]{svninfo}
+\usepackage[automark]{scrpage2}
+\usepackage[ansinew]{inputenc}
+%\usepackage{german}
+%\usepackage{bibgerm}
+\usepackage{amsmath}
+\usepackage{amsfonts}
+\usepackage{theorem}
+\usepackage{tikz}
+\usepackage{color}
+\usepackage{listings}
+\lstset{language=bash, basicstyle=\normalfont\ttfamily\scriptsize,
+ keywordstyle=\color{black}\bfseries, tabsize=4,
+ stringstyle=\ttfamily, commentstyle=\it, extendedchars=true}
+\usepackage{hyperref}
+\usepackage{makeidx}
+\usepackage{xspace}
+
+\usepackage{graphicx}
+
+\newtheorem{lst}{Listing}
+\newtheorem{remark}{Remark}[section]
+
+\newcommand{\dune}{\texttt{DUNE}\xspace}
+\newcommand{\autoconf}{\texttt{autoconf}\xspace}
+\newcommand{\automake}{\texttt{automake}\xspace}
+\newcommand{\autogen}{\texttt{dune-autogen}\xspace}
+\newcommand{\libtool}{\texttt{libtool}\xspace}
+\newcommand{\configure}{\texttt{configure}\xspace}
+\newcommand{\configureac}{\texttt{configure.ac}\xspace}
+\newcommand{\makefile}{\texttt{Makefile}\xspace}
+\newcommand{\makefilein}{\texttt{Makefile.in}\xspace}
+\newcommand{\makefileam}{\texttt{Makefile.am}\xspace}
+\newcommand{\dunecommon}{\texttt{dune-common}\xspace}
+\newcommand{\duneistl}{\texttt{dune-istl}\xspace}
+\newcommand{\dunegrid}{\texttt{dune-grid}\xspace}
+\newcommand{\dunegridhowto}{\texttt{dune-grid-howto}\xspace}
+\newcommand{\dunegriddevhowto}{\texttt{dune-grid-dev-howto}\xspace}
+\newcommand{\dunecontrol}{\texttt{dunecontrol}\xspace}
+\newcommand{\duneproject}{\texttt{duneproject}\xspace}
+\newcommand{\dunemodule}{\texttt{dune.module}\xspace}
+\newcommand{\make}{\texttt{make}\xspace}
+\newcommand{\topsrc}{\$(top\_srcdir)}
+
+\newcommand{\executable}[1]{{\em #1}\xspace}
+
+\pagestyle{scrheadings}
+
+\title{The DUNE Buildsystem HOWTO}
+
+\author{Christian Engwer$^\ast$
+% \and Felix Albrecht$^\dagger$
+}
+
+%\date{\svnToday}
+\date{March 1 2009}
+
+\publishers{%
+\vspace{10mm}
+{\normalsize $^\ast$Interdisziplin\"ares Zentrum f\"ur Wissenschaftliches Rechnen,
+Universit\"at Heidelberg,\\
+Im Neuenheimer Feld 368, D-69120 Heidelberg, Germany}\\
+%
+% \bigskip
+% {\normalsize $^\dagger$Institut f\"ur Numerische und Angewandte Mathematik,
+% Westf\"alische Wilhelms-Universit\"at M\"unster,\\
+% Einsteinstr. 62, D-48149 M\"unster, Germany}\\
+% %
+\bigskip
+{\normalsize \url{http://www.dune-project.org/}}\\
+}
+
+\begin{document}
+
+\maketitle
+\tableofcontents
+\pagebreak
+
+\section{Getting started}\label{section::getting_started}
+
+\textbf{TODO: How do I build the grid howto?}
+
+\section{Creating a new \dune project}\label{section::creating_new_dune_project}
+
+From a build system point of view there is no difference between a \dune
+application and a \dune module.
+
+\dune modules are packages that offer a certain functionality that can
+be used by \dune applications. Therefore \dune modules offer libraries
+and/or header files. A \dune module needs to comply with certain rules
+(see~\ref{guidelines}).
+
+Creating a new \dune project has been covered in detail in
+\ref{section::creating_dune_module} using \texttt{duneproject} to take
+work off of the user. This is also the recommended way to start a new project.
+If for whatever reasons you do not wish to use \duneproject here is
+the bare minimum you have to provide in order to create a new project:
+\begin{itemize}
+\item a \dunemodule file\\
+ Usually you will only need to specify the parameters \texttt{Module}
+ and \texttt{Depends}.
+\item \emph{Note:} an \autogen script is \emph{not} needed any more!
+\item a basic m4 file\\
+ You need to provide two macros \texttt{\emph{MODULE}\_CHECKS}
+ and \texttt{\emph{MODULE}\_CHECK\_MODULE} (see~\ref{m4files}).
+\item a \configureac file\\
+ Have look at the \configureac in \dunegrid for example. The most
+ important part is the call to \texttt{DUNE\_CHECK\_ALL} which
+ runs all checks needed for a \dune module, plus the checks for the
+ dependencies.
+\end{itemize}
+
+\subsection{Configuring new \dune module using \duneproject}\label{section::creating_dune_module}
+
+This section tells you how to begin working with \dune without explaining any
+further details. For a closer look on \duneproject, see section
+\ref{section::creating_new_dune_project}.
+
+Once you have downloaded all the \dune modules you are interested in, you probably
+wonder ``How do I start working with \dune?'' It is quite easy.
+Let us assume you have a terminal open and are inside a directory containing
+some \dune modules. Let us say
+
+\begin{lstlisting}[language=make]
+ls -l
+\end{lstlisting}
+produces something like:
+
+\begin{lstlisting}[language=make]
+dune-common/
+dune-grid/
+config.opts
+\end{lstlisting}
+
+There is no difference between a \dune module you have downloaded from
+the web and modules you created yourself.
+\dunecontrol takes care of configuring your project and creating the
+correct \texttt{Makefile}s (so you can easily link and use all the other \dune
+modules). It can be done by calling
+
+\begin{lstlisting}[language=make]
+./dune-common/bin/duneproject
+\end{lstlisting}
+
+\emph{Note:} In case you are using the unstable version
+\dune you should be aware that the build system may change,
+just like the source code. Therefore it might be that
+\texttt{duneproject} is not up to date with the latest changes.
+
+After calling \duneproject, you have to provide a name for your project
+(without whitespace), e.g., \texttt{dune-foo}.
+The prefix \texttt{dune-} is considered good practice, but it is not
+mandatory.
+You are then asked to provide a
+list of all modules the new project should depend on (this will be
+something like \dunecommon \dunegrid, etc.). At last, you should provide
+the version of your project (e.g., \texttt{0.1}) and your email address.
+\duneproject now creates your new project which is a folder with the name of your project,
+containing some files needed in order to work with \dune.
+In our example,
+
+\begin{lstlisting}[language=make]
+ls -l dune-foo/
+\end{lstlisting}
+should produce something like
+
+\begin{lstlisting}[language=make]
+configure.ac
+dune.module
+Makefile.am
+README
+src
+ --> dune-foo.cc
+doc
+\end{lstlisting}
+
+You can now call \dunecontrol for your new project, as you would for any other \dune module. If you have a \texttt{config.opts}\xspace
+file configured to your needs (see e.g. the ``Installation Notes'' on
+\url{http://www.dune-project.org}), a simple call of
+
+\begin{lstlisting}[language=make]
+./dune-common/bin/dunecontrol --module=dune-foo --opts=config.opts all
+\end{lstlisting}
+should call \autogen, \configure and \make for your
+project and all modules your project depends on first.
+
+\begin{remark}
+Always call \dunecontrol from the directory containing \dunecommon.
+\end{remark}
+
+You can now simply run
+
+\begin{lstlisting}[language=make]
+./dune-foo/src/dune-foo
+\end{lstlisting}
+which should produce something like
+
+\begin{lstlisting}[language=make]
+Hello World! This is dune-foo.
+This is a sequential program.
+\end{lstlisting}
+
+If you want your \dune module to be usable by other people your
+design should follow a certain structure. A good way to indicate that
+your module is set up like the other \dune modules is by naming it
+with the prefix \texttt{dune-}\xspace. Since your module should be
+concerned with a certain topic, you should give it a meaningful name
+(e.g. \dunegrid is about grids). You will also see that there are
+subfolders \texttt{doc/}\xspace, \texttt{foo/}\xspace and
+\texttt{src/}\xspace in \texttt{dune-foo/}\xspace.
+\texttt{foo/}\xspace will contain any headers that are of interest to
+other users (like the subfolder \texttt{common/}\xspace in
+\dunecommon, \texttt{grid/}\xspace in \dunegrid, etc.). Other users
+will have to include those files if they want to work with them. Let's
+say your project provides some interface implementation in a file
+\texttt{foo.hh}\xspace. \duneproject already put this an example file
+into the subfolder \texttt{dune/foo/}.
+
+\begin{lstlisting}[language=make]
+dune-foo/
+-> configure.ac
+-> doc/
+ -> doxygen/
+ -> Doxylocal
+ -> Makefile.am
+ -> Makefile.am
+-> dune.module
+-> dune/
+ -> foo/
+ -> foo.hh
+ -> Makefile.am
+ -> Makefile.am
+-> Makefile.am
+-> README
+-> src/
+ -> dune_foo.cc
+\end{lstlisting}
+
+After running
+\begin{lstlisting}[language=make]
+make doc
+\end{lstlisting}
+in \texttt{dune-foo} you should now find a
+\texttt{html} \texttt{doxygen} documentation which can be read by opening
+\texttt{dune-foo/doc/doxygen/html/index.html}.
+
+\section{Dune module guidelines}\label{section::dune_module_guidelines}
+\label{guidelines}
+
+A \dune module should comply with the following rules:
+\begin{itemize}
+\item Documentation is located under \texttt{doc/} and gets
+ web-installed under \texttt{BASEDIR/doc/}.
+\item \automake includes are located in \dunecommon. To use them, you
+ will have to make a symbolic link to \texttt{dune-common/am/} (see
+ \ref{am_includes}). The symlink creation should be handled by the
+ \autogen (see~\ref{autogen}).
+\item The \texttt{am/} directory does not get included in the tarball.
+\item Additional configure tests are located in the \texttt{m4/}
+ directory. You should at least provide the macros \texttt{\emph{MODULE}\_CHECKS}
+ and \texttt{\emph{MODULE}\_CHECK\_MODULE}, in order to setup and
+ find your module (see~\ref{m4files}).
+\item Header files should be accessible via \verb!#include <dune/foo/bar.hh>!,
+ otherwise they cannot be used by other \dune modules. When running
+ \texttt{make install} all header files should be installed into
+ \texttt{\textit{prefix}/include/dune/}.
+\end{itemize}
+
+\section{The Structure of \dune}
+\dune consists of several independent modules:
+\begin{itemize}
+\item \dunecommon
+\item \dunegrid
+\item \duneistl
+\item \dunegridhowto
+\item \dunegriddevhowto
+\end{itemize}
+
+Single modules can depend on other modules and so the \dune modules
+form a dependency graph. The build system has to track and resolve
+these inter-module dependencies.
+
+The build system is structured as follows:
+\begin{itemize}
+\item Each module is built using the GNU AutoTools.
+\item Each module has a set of modules it depends on, these modules
+ have to be built before building the module itself.
+\item Each module has a file \dunemodule which holds dependencies and
+ other information regarding the module.
+\item The modules can be built in the appropriate order using the
+ \dunecontrol script (shipped with \dunecommon)
+\end{itemize}
+
+The reasons to use the GNU AutoTools for \dune were the following
+\begin{itemize}
+\item We need platform independent build.
+\item Enabling or disabling of certain features depending on
+ features present on the system.
+\item Creations of libraries on all platforms.
+\item Easy creation of portable but flexible Makefiles.
+\end{itemize}
+
+The reasons to add the \dunecontrol script and the \dunemodule
+description files were
+\begin{itemize}
+\item One tool to setup all modules (the AutoTools can only work on one
+ module).
+\item Automatic dependency tracking.
+\item Automatic collection of command-line parameters (\configure needs
+ special command-line parameters for all modules it uses)
+\end{itemize}
+
+\section{Building Single Modules Using the GNU AutoTools}
+
+Software is generally developed to be used on multiple
+platforms. Since each of these platforms has different compilers,
+different header files, there is a need to write makefiles and build
+scripts that work on a variety of platforms. The Free
+Software Foundation (FSF), faced with this problem, devised a
+set of tools to generate makefiles and build scripts that work on a
+variety of platforms. These are the GNU AutoTools.
+If you have downloaded and built any GNU
+software from source, you are familiar with the \configure script. The
+\configure script runs a series of tests to get information about
+your machine.
+
+The autotools simplify the generation of portable Makefiles and
+configure scripts.
+
+\minisec{autoconf}
+
+\autoconf is used to create the \configure script. \configure is
+created from \configureac, using a set of \texttt{m4} files.
+
+\begin{center}
+ \begin{tikzpicture}[scale=0.05,line width=1pt,rounded corners=8pt]
+ \draw (-2,2) node [anchor=south] {\configureac}
+ -- (-2,-2) -- (67.5,-2) -- (67.5,-6);
+ \draw (137,2) node [anchor=south] {\tt{}m4/*.m4}
+ -- (137,-2) -- (67.5,-2) -- (67.5,-6);
+ \draw[->] (67.5,-5.5)
+ -- (67.5,-10) node [anchor=west] {\textit{\autoconf}}
+ -- (67.5,-20) node [anchor=north] {\configure};
+ \end{tikzpicture}
+\end{center}
+
+How to write a \configureac for \dune is described in Sec.\,\ref{configure.ac}.
+
+\minisec{automake}
+
+\automake is used to create the \makefilein files (needed for
+\configure) from \makefileam files, using a set of include files
+located in a directory called \texttt{am}. These include files provide
+additional features not provided by the standard \automake (see
+Sec.\,\ref{am_includes}). The \texttt{am} directory is in the \dunecommon
+module and each module intending to use one of these includes has to
+have a symlink \texttt{am} that points to \texttt{dune-common/am}.
+This link is usually created by \autogen (see Sec.\,\ref{autogen}).
+
+\begin{center}
+ \begin{tikzpicture}[scale=0.05,line width=1pt,rounded corners=8pt]
+ \draw (-2,2) node [anchor=south] {\makefileam}
+ -- (-2,-2) -- (67.5,-2) -- (67.5,-6);
+ \draw (137,2) node [anchor=south] {\tt{}am/*}
+ -- (137,-2) -- (67.5,-2) -- (67.5,-6);
+ \draw[->] (67.5,-5.5)
+ -- (67.5,-10) node [anchor=west] {\textit{\automake}}
+ -- (67.5,-20) node [anchor=north] {\texttt{Makefile.in}};
+ \draw[dashed, ->] (67.5,-30)
+ -- (67.5,-37) node [anchor=west] {\textit{\configure}}
+ -- (67.5,-44) node [anchor=north] {\texttt{Makefile}};
+ \end{tikzpicture}
+\end{center}
+
+Information on writing a \makefileam is described in \ref{makefile.am}
+
+\minisec{libtool}
+\libtool is a wrapper around the compiler and
+linker. It offers a generic interface for creating static and shared
+libraries, regardless of the platform it is running on.
+
+\libtool hides all the platform specific aspects of library creation
+and library usage. When linking a library or an executable you (or
+\automake) can call the compiler via \libtool. \libtool will then take
+care of
+\begin{itemize}
+\item platform specific command-line parameters for the linker,
+\item library dependencies.
+\end{itemize}
+
+\minisec{configure}
+\label{configure}
+\configure will run the set of tests specified in your \configureac.
+Using the results of these tests configure can check that all
+necessary features (libraries, programs, etc.) are present and can activate
+and deactivate certain features of the module depending on what is
+available on your system.
+
+For example \configure in \dunegrid will search for the ALUGrid
+library and enable or disable \texttt{Dune::ALU3dGrid}.
+This is done by writing a preprocessor macro \verb!#define HAVE_ALUGRID!
+in the \texttt{config.h}
+header file. A header file can then use an \verb!#ifdef! statement to
+disable parts of the code that do not work without a certain
+feature. This can be used in the applications as well as in the headers
+of a \dune module.
+
+The \texttt{config.h} file is created by \configure from a
+\texttt{config.h.in} file, which is automatically created from the
+list of tests used in the \configureac.
+
+\subsection{Makefile.am}
+\label{makefile.am}
+
+\subsubsection{Overview}
+
+Let's start off with a simple program \executable{hello} built from
+\texttt{hello.c}. As \automake is designed to build and install a
+package it needs to know
+
+\begin{itemize}
+\item what programs it should build,
+\item where to put them when installing,
+\item which sources to use.
+\end{itemize}
+
+The core of a \makefileam thus looks like this:
+
+\begin{lstlisting}[language=make]
+noinst_PROGRAMS = hello
+hello_SOURCES = hello.c
+\end{lstlisting}
+
+This would build \executable{hello} but not install it when \texttt{make
+ install} is called. Using \verb!bin_PROGRAMS! instead of
+\verb!noinst_PROGRAMS! would install the \executable{hello}-binary into a
+\texttt{\textit{prefix}/bin} directory.
+
+Building more programs with several source files works like this
+
+\begin{lstlisting}[language=make]
+noinst_PROGRAMS = hello bye
+
+hello_SOURCES = common.c common.h hello.c
+bye_SOURCES = common.c common.h bye.c parser.y lexer.l
+\end{lstlisting}
+
+\automake has more integrated rules than the standard make, the example
+above would automatically use yacc/lex to create
+\texttt{parser.c/lexer.c} and build them into the {\em bye} binary.
+
+Make-Variables may be defined and used as usual:
+
+\begin{lstlisting}[language=make]
+noinst_PROGRAMS = hello bye
+
+COMMON = common.c common.h
+
+hello_SOURCES = $(COMMON) hello.c
+bye_SOURCES = $(COMMON) bye.c parser.y lexer.l
+\end{lstlisting}
+
+Even normal make-rules may be used in a \makefileam.
+
+\minisec{Using flags}
+
+Compiler/linker/preprocessor-flags can be set either globally:
+
+\begin{lstlisting}[language=make]
+noinst_PROGRAMS = hello bye
+
+AM_CPPFLAGS = -DDEBUG
+
+hello_SOURCES = hello.c
+bye_SOURCES = bye.c
+\end{lstlisting}
+
+or locally:
+
+\begin{lstlisting}[language=make]
+noinst_PROGRAMS = hello bye
+
+hello_SOURCES = hello.c
+hello_CPPFLAGS = -DHELLO
+
+bye_SOURCES = bye.c
+bye_CPPFLAGS = -DBYE
+\end{lstlisting}
+
+The local setting overrides the global one, thus
+
+\begin{lstlisting}[language=make]
+hello_CPPFLAGS = $(AM_CPPFLAGS) -Dmyflags
+\end{lstlisting}
+%$\end{lstlisting}
+
+may be a good idea.
+
+It is even possible to compile the same sources with different flags:
+
+\begin{lstlisting}[language=make]
+noinst_PROGRAMS = hello bye
+
+hello_SOURCES = generic-greeting.c
+hello_CPPFLAGS = -DHELLO
+
+bye_SOURCES = generic-greeting.c
+bye_CPPFLAGS = -DBYE
+\end{lstlisting}
+
+Perhaps you're wondering why the above examples used
+\texttt{AM\_CPPFLAGS} instead of normal \texttt{CPPFLAGS}? The
+reason for this is that the variables \texttt{CFLAGS},
+\texttt{CPPFLAGS}, \texttt{CXXFLAGS} etc. are considered {\em user
+ variables} which may be set on the command line:
+
+\begin{lstlisting}[language=make]
+make CXXFLAGS="-O2000"
+\end{lstlisting}
+
+This would override any settings in Makefile.am which might be
+necessary to build. Thus, if the variables should be set even if the
+user wishes to modify the values, you should use the \texttt{AM\_*}
+version.
+
+The real compile-command always uses both \texttt{AM\_\textit{VAR}} and
+\texttt{\textit{VAR}} (or \texttt{\texttt{progname}\_\textit{VAR}} and
+\texttt{\textit{VAR}}). Options that
+autoconf finds are stored in the user variables (so that they may be
+overridden).
+
+Besides the three types of variables mentioned so far (user-, automake- and
+program-variables) there exists a fourth type by convention: variables of
+dependent libraries. These variables have the form
+\texttt{\textit{LIBRARY}\_\textit{VAR}} and contain flags necessary to build
+programs or libraries which depend on that library. They are usually included
+in \texttt{\textit{program}\_\textit{VAR}}, like this:
+\begin{lstlisting}[language=make]
+foo_CPPFLAGS = $(AM_CPPFLAGS) $(SUPERLU_CPPFLAGS)
+\end{lstlisting}
+If all programs build by the same makefile depend on a library,
+\texttt{\textit{program}\_\textit{VAR}} can be included in
+\texttt{AM\_\textit{VAR}} instead:
+\begin{lstlisting}[language=make]
+AM_CPPFLAGS = @AM_CPPFLAGS@ $(SUPERLU_CPPFLAGS)
+\end{lstlisting}
+%$\end{lstlisting}
+
+There are five classes of variables in automake-generated makefiles:
+\begin{description}
+\item[automake] Example: \texttt{AM\_CPPFLAGS}. These variables are usually
+ undefined by default and the developer may assign them default values in the
+ \texttt{Makefile.am}:
+ \begin{lstlisting}[language=make]
+AM_CPPFLAGS = -DMY_DIR=`pwd`
+ \end{lstlisting}
+ {\bf Automake} variables are not automatically substituted by
+ \texttt{configure}, though it is common for the developer to
+ \lstinline[language=make]{AC_SUBST} them. In this case a different
+ technique must be used to assign values to them, or the substituted value
+ will be ignored. See the {\bf configure-substituted} class below. The
+ names of {\bf automake} variables begin with \texttt{AM\_} most of the time,
+ but there are some variables which don't have that prefix. These variables
+ give defaults for {\bf target-specific} variables.
+\item[configure-substituted] Example: \lstinline[language=make]{srcdir}.
+ Anything can be made a {\bf configure-substituted} variable by calling
+ \lstinline[language=sh]{AC_SUBST} in \texttt{configure.ac}. Some
+ variables always substituted by autoconf\footnote{autoconf manual, section
+ ``Preset Output Variables''} or automake, others are only substituted when
+ certain autoconf macros are used. In Dune, it is quiet common to substitute
+ {\bf automake} variables:
+ \begin{lstlisting}[language=sh]
+AC_SUBST(AM_CPPFLAGS, $DUNE_CPPFLAGS)
+ \end{lstlisting}
+ %$\end{lstlisting}
+ The value substituted by \texttt{configure} can be augmented in the
+ \texttt{Makefile.am} like this:
+ \begin{lstlisting}[language=make]
+AM_CPPFLAGS = @AM_CPPFLAGS@ -DMY_DIR=`pwd`
+ \end{lstlisting}
+\item[target-specific] Example: \texttt{\textit{target}\_CPPFLAGS}. The names
+ of these variables are of the form canonical target name followed by an
+ underscore followed some uppercase letters. If there is a {\bf automake}
+ variable corresponding to this {\bf target-specific} variable, the uppercase
+ letters at the end of the name usually correspond to the name of that {\bf
+ automake} variable. These variables provide target-specific information.
+ They are defined by the developer in the \texttt{Makefile.am} and are
+ documented in the automake manual. If there is corresponding a {\bf
+ automake} variable it provides a default which is used when the {\bf
+ target-specific} variable is not defined. Example definition:
+ \begin{lstlisting}[language=make]
+false_SOURCES = true.c
+false_CPPFLAGS = $(AM_CPPFLAGS) -DEXIT_CODE=1
+ \end{lstlisting}
+ %$\end{lstlisting}
+ This example also shows how to include the value of the corresponding {\bf
+ automake} variable.
+\item[user] Example: \texttt{CPPFLAGS}. These variables are for the user to
+ set on the make command line:
+ \begin{lstlisting}[language=sh]
+make CPPFLAGS=-DNDEBUG
+ \end{lstlisting}
+ They usually augment some {\bf target-specific} or {\bf makefile-default}
+ variable in the build rules. Often these variables are {\em
+ precious}\footnote{autoconf manual,
+ \lstinline[language=sh]{AC_ARG_VAR}}, and the user can tell
+ \texttt{configure} what values these variables should have. These variables
+ are {\bf configure-substituted}.
+
+ The developer should never set this
+ variables in the \texttt{Makefile.am}, because that would override the
+ user-provided values given to configure. Instead, \texttt{configure.ac}
+ must be tweaked to set a different default if the user does not give a value
+ to \texttt{configure}.
+\item[external-library] Example: \texttt{\textit{LIB}CPPFLAGS}. These
+ variables contain settings needed when using external libraries in a
+ target. They should be included in the value for the corresponding {\bf
+ target-specific} variable
+ \begin{lstlisting}[language=make]
+testprog_CPPFLAGS = $(AM_CPPFLAGS) $(SUPERLUCPPFLAGS)
+ \end{lstlisting}
+ or the {\bf makefile-default} variable
+ \begin{lstlisting}[language=make]
+AM_CPPFLAGS = @AM_CPPFLAGS@ $(SUPERLUCPPFLAGS)
+ \end{lstlisting}
+ %$\end{lstlisting}
+ Values for these variables are determined by \texttt{configure}, thus they
+ are {\bf configure-substituted}. Usually,
+ \texttt{configure.ac} must call the right autoconf macro to determine these
+ variables.
+
+ Note that the variable name with an underscore
+ \texttt{\textit{LIB}\_CPPFLAGS} is not recommended\footnote{Autoconf
+ manual, section ``Flag Variables Ordering''}, although this pattern is
+ common.
+\end{description}
+
+Commonly used variables are:
+\begin{description}
+\item[preprocessor flags] These flags are passed in any build rule that calls
+ the preprocessor. If there is a {\bf target-specific} variable
+ \texttt{\textit{target}\_CPPFLAGS} defined, the flags are given by
+\begin{lstlisting}[language=make]
+$(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(target_CPPFLAGS) $(CPPFLAGS)
+\end{lstlisting}
+ %$\end{lstlisting}
+ otherwise
+\begin{lstlisting}[language=make]
+$(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS)
+\end{lstlisting}
+ %$\end{lstlisting}
+ is used.
+ \begin{description}
+ \item[\texttt{DEFS}] Class: {\bf configure-substituted}. Contains all the
+ preprocessor defines from \lstinline[language=sh]{AC_DEFINE} and friends.
+ If a \texttt{config.h} header is used, contains just the value
+ \texttt{-DHAVE\_CONFIG\_H} instead.
+ \item[\texttt{DEFAULT\_INCLUDES}] Class: {\bf configure-substituted}. This
+ variables contains a set of default include paths: \texttt{-I.},
+ \texttt{-I\$(srcdir)}, and an path to the directory of \texttt{config.h},
+ if that is used.
+ \item[\texttt{INCLUDES}] Class: {\bf automake}. This is an obsolete
+ alternative to \texttt{AM\_CPPFLAGS}. Use that instead.
+ \item[\texttt{\textit{target}\_CPPFLAGS}] Class: {\bf target-specific}.
+ Target-specific preprocessor flags. If this variable exists, it overrides
+ \texttt{AM\_CPPFLAGS} and causes the renaming of object
+ files\footnote{automake manual, ``Why are object files sometimes
+ renamed?''}.
+ \item[\texttt{AM\_CPPFLAGS}] Class: {\bf automake}. This is the makefile
+ default for any preprocessor flags.
+ \item[\texttt{CPPFLAGS}] Class: {\bf user}, {\bf configure-substituted}.
+ Flags given by the user, either to \texttt{configure} or when invoking
+ \texttt{make}. If the user didn't provide any value to
+ \texttt{configure}, it may contain debugging and optimization options per
+ default (like \texttt{-DNDEBUG}). The value of \texttt{CPPFLAGS} always
+ appears after the other preprocessor flags.
+ \item[\texttt{\textit{LIB}CPPFLAGS}] Class: {\bf external-library}.
+ Preprocessor flags when building with library \textit{LIB}. This variable
+ should be include in \texttt{\textit{target}\_CPPFLAGS} or
+ \texttt{AM\_CPPFLAGS} in the \texttt{Makefile.am}.
+ \end{description}
+
+\item[C-compiler flags] These flags are passed in any build rule that calls
+ the C compiler or the C linker. If there is a {\bf target-specific}
+ variable \texttt{\textit{target}\_CFLAGS} defined, the flags are given by
+\begin{lstlisting}[language=make]
+$(target_CFLAGS) $(CFLAGS)
+\end{lstlisting}
+ otherwise
+\begin{lstlisting}[language=make]
+$(AM_CFLAGS) $(CFLAGS)
+\end{lstlisting}
+ is used.
+ \begin{description}
+ \item[\texttt{\textit{target}\_CFLAGS}] Class: {\bf target-specific}.
+ Target-specific C compiler flags. If this variable exists, it overrides
+ \texttt{AM\_CFLAGS} and causes the renaming of object
+ files\footnote{automake manual, ``Why are object files sometimes
+ renamed?''}.
+ \item[\texttt{AM\_CFLAGS}] Class: {\bf automake}. This is the makefile
+ default for any C compiler flags.
+ \item[\texttt{CFLAGS}] Class: {\bf user}, {\bf configure-substituted}.
+ Flags given by the user, either to \texttt{configure} or when invoking
+ \texttt{make}. If the user didn't provide any value to
+ \texttt{configure}, it may contain debugging, optimization and warning
+ options per default (like \texttt{-g -O2 -Wall}). The value of
+ \texttt{CFLAGS} always appears after the other C compiler flags.
+ \end{description}
+
+\item[C++-compiler flags] These flags are passed in any build rule that calls
+ the C++ compiler or the C++ linker. If there is a {\bf target-specific}
+ variable \texttt{\textit{target}\_CXXFLAGS} defined, the flags are given by
+\begin{lstlisting}[language=make]
+$(target_CXXFLAGS) $(CXXFLAGS)
+\end{lstlisting}
+ otherwise
+\begin{lstlisting}[language=make]
+$(AM_CXXFLAGS) $(CXXFLAGS)
+\end{lstlisting}
+ is used.
+ \begin{description}
+ \item[\texttt{\textit{target}\_CXXFLAGS}] Class: {\bf target-specific}.
+ Target-specific C++ compiler flags. If this variable exists, it overrides
+ \texttt{AM\_CXXFLAGS} and causes the renaming of object
+ files\footnote{automake manual, ``Why are object files sometimes
+ renamed?''}.
+ \item[\texttt{AM\_CXXFLAGS}] Class: {\bf automake}. This is the makefile
+ default for any C++ compiler flags.
+ \item[\texttt{CXXFLAGS}] Class: {\bf user}, {\bf configure-substituted}.
+ Flags given by the user, either to \texttt{configure} or when invoking
+ \texttt{make}. If the user didn't provide any value to
+ \texttt{configure}, it may contain debugging, optimization and warning
+ options per default (like \texttt{-g -O2 -Wall}). The value of
+ \texttt{CXXFLAGS} always appears after the other C++ compiler flags.
+ \end{description}
+
+\item[linker flags] These flags are passed in any build rule that calls the
+ linker. If there is a {\bf target-specific} variable
+ \texttt{\textit{target}\_LDFLAGS} defined, the flags are given by
+\begin{lstlisting}[language=make]
+$(target_LDFLAGS) $(LDFLAGS)
+\end{lstlisting}
+ otherwise
+\begin{lstlisting}[language=make]
+$(AM_LDFLAGS) $(LDFLAGS)
+\end{lstlisting}
+ is used. These variables are inappropriate to pass any options or parameters
+ that specify libraries of object files, in particular \texttt{-L} or
+ \texttt{-l} or the libtool options \texttt{-dlopen} and \texttt{-dlpreopen}.
+ Use a variable from the {\em libraries to link to} set to do that.
+ \begin{description}
+ \item[\texttt{\textit{target}\_LDFLAGS}] Class: {\bf target-specific}.
+ Target-specific C++ compiler flags. If this variable exists, it overrides
+ \texttt{AM\_LDFLAGS}. The existence of this variable does {\em not} cause
+ renaming of object files\footnote{automake manual, ``Why are object files
+ sometimes renamed?''}.
+ \item[\texttt{AM\_LDFLAGS}] Class: {\bf automake}. This is the makefile
+ default for any linker flags.
+ \item[\texttt{LDFLAGS}] Class: {\bf user}, {\bf configure-substituted}.
+ Flags given by the user, either to \texttt{configure} or when invoking
+ \texttt{make}. If the user didn't provide any value to
+ \texttt{configure}, it may contain debugging, optimization and warning
+ options per default. The value of \texttt{LDFLAGS} always appears after
+ the other linker flags.
+ \item[\texttt{\textit{LIB}LDFLAGS}] Class: {\bf external-library}. Linker
+ flags needed when linking to library \textit{LIB}. This variable should
+ be include in \texttt{\textit{target}\_LDFLAGS} or \texttt{AM\_LDFLAGS} in
+ the \texttt{Makefile.am}.
+ \end{description}
+
+\item[libraries to link to] These variables are used to determine the
+ libraries and object files to link to. They are passed whenever the linker
+ is called. When
+ linking a program, extra libraries and objects to link to are given by
+ \begin{lstlisting}[language=make]
+$(target_LDADD) $(LIBS)
+ \end{lstlisting}
+ If the {\bf target-specific} variable \texttt{\textit{target}\_LDADD} is not
+ defined, automake supplies
+ \begin{lstlisting}[language=make]
+target_LDADD = $(LDADD)
+ \end{lstlisting}
+ %$\end{lstlisting}
+ When linking a library, extra libraries and objects to link to are given by
+ \begin{lstlisting}[language=make]
+$(target_LIBADD) $(LIBS)
+ \end{lstlisting}
+ If the {\bf target-specific} variable \texttt{\textit{target}\_LIBADD} is
+ not defined, automake defines it empty
+ \begin{lstlisting}[language=make]
+target_LIBADD =
+ \end{lstlisting}
+ Libraries and objects to link to must be given in reverse order: a library
+ or object file must come before the libraries or object files it depends on
+ on the linker command line. Thus the value of the \texttt{LIBS} variable is
+ included after the value of the \texttt{\textit{target}\_LDADD} or
+ \texttt{\textit{target}\_LIBADD} variable.
+
+ In general, any linker flags and argument that specify libraries and object
+ files should be included in these variables, and nothing else. In
+ particular that means library and object file names, the options \texttt{-L}
+ and \texttt{-l}, and the libtool options \texttt{-dlopen} and
+ \texttt{-dlpreopen}. The option \texttt{-L} should come directly before any
+ \texttt{-l} options it sets the linker path for, otherwise a path set by
+ another \texttt{-L} option may take precedence, which may happen to contain
+ a library by the same name.
+ \begin{description}
+ \item[\texttt{\textit{target}\_LDADD}] Class: {\bf target-specific}.
+ Target-specific libraries and objects to link to {\em for programs}. If
+ this variable does not exist, it defaults to \texttt{\$(LDADD)}.
+ \item[\texttt{LDADD}] Class: {\bf automake}. Libraries and objects
+ to link to {\em for programs}. Default for
+ \texttt{\textit{target}\_LDADD}.
+ \item[\texttt{\textit{target}\_LIBADD}] Class: {\bf target-specific}.
+ Target-specific objects to link to {\em for libraries}. If the target is
+ a libtool library, then other libtool libraries may also be specified
+ here. This variable has no makefile-wide default, if it does not exist
+ the empty value is assumed.
+ \item[\texttt{LIBS}] Class: {\bf automake}, {\bf configure-substituted}.
+ Libraries discovered by configure.
+ \item[\texttt{\textit{LIB}LIBS}] Class: {\bf external-library}. Libraries
+ and object files needed to linking against library \textit{LIB}, including
+ that library itself. This variable should be include in
+ \texttt{\textit{target}\_LDADD}, \texttt{LDADD}, or
+ \texttt{\textit{target}\_LIBADD} in the \texttt{Makefile.am}.
+ \end{description}
+\end{description}
+
+\minisec{Individual library variables}
+
+\begin{description}
+\item[MPI] The \texttt{DUNE\_MPI} macro sets the following variables with the
+ help of the macros \texttt{MPI\_CONFIG} and \texttt{ACX\_MPI}: For
+ compilation with the MPI compiler \texttt{MPICC} and \texttt{MPILIBS}.
+ These are not used in \dune except that \texttt{MPICC} may be set on the
+ configure command line to select which MPI installation to use. For
+ compilation with the standard compiler it sets \texttt{DUNEMPICPPFLAGS},
+ \texttt{DUNEMPILDFLAGS} and \texttt{DUNEMPILIBS}, and the deprecated
+ variables \texttt{MPI\_CPPFLAGS} and \texttt{MPI\_LDFLAGS} (note there is no
+ \texttt{MPI\_LIBS}). Unfortunately with most MPI implementations it is
+ impossible to obtain the linker flags separately from the libraries to link
+ to. Therefore, this macro stuffs everything into \texttt{DUNEMPILIBS},
+ which has the advantage that it works and the disadvantage that users are
+ unable to overwrite the linker flags. If that is a problem users should set
+ these variables themselves on the configure command line.
+
+ In addition, this macro substitutes \texttt{MPI\_VERSION} a text string
+ identifying the detected version of MPI. It defines the following
+ preprocessor defines: \texttt{MPI\_2}, defined if the detected MPI supports
+ the MPI-2 standard. \texttt{HAVE\_MPI}, 1 if MPI is detected and enabled.
+ It also defines the automake conditional \texttt{MPI}.
+\item[\dune modules] For each \dune module there are the variables
+ \texttt{\textit{MODULE}\_CPPFLAGS}, \texttt{\textit{MODULE}\_LDFLAGS} and
+ \texttt{\textit{MODULE}\_LIBS}. They contain everything to use that module
+ with its most basic functionality. For instance, for \texttt{dune-grid}
+ they do not contain the stuff for MPI, Alberta, ALU Grid or UG, even if
+ those were detected. They do contain the stuff for \texttt{dune-common},
+ possibly with duplicates removed, since that is absolutely required for the
+ operation of \texttt{dune-grid}. Example use:
+ \begin{lstlisting}[language=make]
+foo_SOURCES = foo.cc
+foo_CPPFLAGS = $(AM_CPPFLAGS) \
+ $(UG_CPPFLAGS) \
+ $(DUNE_GRID_CPPFLAGS)
+foo_LDFLAGS = $(AM_LDFLAGS) \
+ $(UG_LDFLAGS) \
+ $(DUNE_GRID_LDFLAGS)
+foo_LDADD = \
+ $(DUNE_GRID_LIBS) \
+ $(UG_LIBS) \
+ $(LDADD)
+ \end{lstlisting}
+ %$\end{lstlisting}
+ Note that there are no such variables for the current module -- these
+ variables are used in the process of building the current module, so that
+ module is incomplete when detecting these variables. Note also that by
+ ``\dune module'' we mean a software package which uses the \dune
+ build system, not one of the official dune modules.
+\item[Basic \dune] To use the basic functionality of all detected \dune
+ modules, the variables \texttt{DUNE\_CPPFLAGS}, \texttt{DUNE\_LDFLAGS} and
+ \texttt{DUNE\_LIBS} may be used. They collect the contents of all \dune
+ module variables, possibly with duplicates removed.
+\item[Extended \dune] To use \dune with all functionality that requires
+ external libraries, the variables \texttt{ALL\_PKG\_CPPFLAGS},
+ \texttt{ALL\_PKG\_LDFLAGS} and \texttt{ALL\_PKG\_LIBS} may be used. They
+ provide everything necessary to build with any external library detected by
+ configure. In the case of Alberta a choice must be made between 2D and 3D.
+ Here the \texttt{ALL\_PKG\_*} variables just follow the choice of the
+ corresponding \texttt{ALBERTA\_*} variables.
+\end{description}
+
+\minisec{Conditional builds}
+
+Some parts of \dune only make sense if certain add-on packages were
+found. autoconf therefore defines {\em conditionals} which automake can
+use:
+
+\begin{lstlisting}[language=make]
+if OPENGL
+ PROGS = hello glhello
+else
+ PROGS = hello
+endif
+
+hello_SOURCES = hello.c
+
+glhello_SOURCES = glhello.c hello.c
+\end{lstlisting}
+
+This will only build the {\em glhello} program if OpenGL was found. An
+important feature of these conditionals is that they work with any
+make program, even those without a native {\em if} construct like GNU-make.
+
+\minisec{Default targets}
+
+An automake-generated Makefile does not only know the usual {\em all},
+{\em clean} and {\em install} targets but also
+\begin{description}
+\item [tags] travel recursively through the directories and create
+ TAGS-files which can be used in many editors to quickly find where
+ symbols/functions are defined (use emacs-format)
+\item [ctags] the same as "tags" but uses the vi-format for the tags-files
+\item [dist] create a distribution tarball
+\item [check] run a set of regression tests
+\item [distcheck] create a tarball and do a test-build if it really works
+\end{description}
+
+\subsubsection{Building Documentation}
+\label{am_includes}
+
+If you want to build documentation you might need additional make
+rules. \dune offers a set of predefined rules to create certain kinds
+of documentation. Therefor you have to include the appropriate rules
+from the \texttt{am/} directory. These rules are stored in the
+\texttt{dune-common/am/} directory. If you want to use these any of
+these rules in your \dune module or application you will have to
+create a symbolic link to \texttt{dune-common/am/}. The creation of
+this link should be done by the \autogen script.
+
+The build system automatically gives you two targets related to the documentation:
+\begin{description}
+ \item [doc] make the documentation,
+ \item [doc-clean] clean up all documentation-related stuff.
+\end{description}
+
+
+\minisec{doxygen}
+
+The source code documentation system \texttt{doxygen}\xspace is the
+preferable way to document your source and header files.
+
+In order to build \texttt{doxygen} documentation you can include
+\texttt{\$(top\_srcdir)/am/doxygen}. Additionally you have create a
+file \texttt{Doxylocal} which contains your local \texttt{doxygen}
+configuration.
+
+Your \texttt{doxygen} documentation should be located in the
+subdirectory \texttt{doc/doxygen/}\xspace (see ``Coding Style'' in the
+section ``Developing Dune'' on
+\url{http://www.dune-project.org/} for details). \em After
+running \duneproject the basic setup is already done\em.
+
+You should only have one \texttt{doxygen} directory and the files are
+automatically installed into\\
+\texttt{\$prefix/share/doc/\$modulename/doxygen/}. If for any reason
+you really have to change the installation path you can set the
+variable \texttt{doxygendir} \em after \em including \texttt{am/doxygen}.
+
+The file \texttt{doc/doxygen/Doxylocal}\xspace contains the basic
+information where header and source files are located in your
+project. Usually you will not have to adjust this file, it is already
+created by \duneproject. It only
+contains the very basic information. During the \texttt{dune-autogen}\xspace
+run the script \texttt{dunedoxynize}\xspace uses the information contained in
+\texttt{Doxylocal}, merges them with the global \dune \texttt{doxygen}\xspace
+styles and writes \texttt{Doxyfile.in}, which will be translated into a
+full \texttt{Doxyfile}\xspace during the \configure run. For details about
+the configuration of \texttt{doxygen}\xspace and about documenting your
+source code we refer to the \texttt{doxygen}\xspace web-site
+\url{http://www.doxygen.org/}.
+
+\minisec{html pages}
+Webpages are created from wml sources, using the program \texttt{wml}
+(\url{http://thewml.org/}).\\
+\texttt{\$(top\_srcdir)/am/webstuff} contains the necessary rules.
+
+Add all \texttt{html} files to the \texttt{PAGES} variable to build
+and install them.
+
+\hspace*{-2ex}\begin{minipage}{\textwidth}
+\begin{lst}[File Makefile.am] \mbox{}
+\lstinputlisting[language=make]{../Makefile.am}
+\end{lst}
+\end{minipage}
+
+\minisec{\LaTeX documents}
+In order to compile \LaTeX documents you can include
+\texttt{\$(top\_srcdir)/am/latex}. This way you get rules for creation
+of DVI files, PS files and PDF files.
+
+\minisec{SVG graphics}
+SVG graphics can be converted to png, in order to include them into
+the web page. This conversion can be done using inkscape
+(\url{http://www.inkscape.org/}).
+\texttt{\$(top\_srcdir)/am/inkscape.am} offers the necessary rules.
+
+\subsubsection{Automatic testing}
+
+Dune offers several special \make targets, which help you find problems
+in your build system configuration, or in your code.
+
+\begin{description}
+\item[check] You can define lists of regression tests in your
+ \makefileam. These are run when you call \texttt{make check}.
+\item[distcheck] This target is already defined by automake. It
+ creates a tarball, unpacks it, tries to do an out-of-source build
+ and runs the regression tests against this build.
+\item[sourcescheck] This target tries to make sure that you don't
+ forget to install any important headers or source files.
+\item[headercheck] This target tries to make sure that your header
+ files can be parsed and are self-contained.
+\end{description}
+
+\minisec{The check target}
+
+TODO\dots{}
+
+\minisec{The sourcescheck target}
+
+TODO\dots{}
+
+\minisec{The headercheck target}
+
+TODO\dots{}
+
+\subsection{configure.ac}
+\label{configure.ac}
+
+\configureac is a normal text file that contains several \autoconf
+macros. These macros are evaluated by the \texttt{m4} macro processor
+and transformed into a shell script.
+
+\begin{lst}[File dune-common/configure.ac] \mbox{}
+\lstinputlisting{../../configure.ac}
+\end{lst}
+
+We offer a set of macros that can be used in your \configureac:
+
+\begin{itemize}
+\item \texttt{DUNE\_CHECK\_ALL}
+ runs all checks usually needed by a {\em \dune module}.
+ It checks for all dependencies and suggestions and for their
+ prerequisites.
+ In order to make the dependencies known to \configure \autogen calls
+ \texttt{dunecontrol m4create} and write a file
+ \texttt{dependencies.m4}.
+\item \texttt{DUNE\_AUTOBUILD\_FLAGS}
+ adds configure flags needed to create log files for
+ \texttt{dune-autobuild}. If you want to add your module to the
+ \texttt{dune-autobuild} system, you have to call this macro.
+\item \texttt{DUNE\_SUMMARY\_ALL}
+ prints information on the results of all major checks run by
+ \texttt{DUNE\_CHECK\_ALL}.
+\end{itemize}
+
+\texttt{DUNE\_CHECK\_ALL} defines the following
+variables that can be used in the \configure script or in the
+\makefileam:
+
+\begin{itemize}
+\item \texttt{DUNE\textit{\,MODULE\,}\_CPPFLAGS}
+\item \texttt{DUNE\textit{\,MODULE\,}\_LDFLAGS}
+\item \texttt{DUNE\textit{\,MODULE\,}\_LIBS}
+\item \texttt{DUNE\textit{\,MODULE\,}ROOT}
+\end{itemize}
+
+The last step to a complete \configureac is that you tell \autoconf
+which files should be generated by \configure. Therefore you add an
+\texttt{AC\_CONFIG\_FILES([\textit{WhiteSpaceSeparatedListOfFiles}])}
+statement to your \configureac. The list of files should be the list
+of files that are to be generated, not the input---i.e. you would
+write
+\begin{lstlisting}[language=make]
+AC_CONFIG_FILES([Makefile doc/Makefile])
+\end{lstlisting}
+instead of
+\begin{lstlisting}[language=make]
+AC_CONFIG_FILES([Makefile.in doc/Makefile.in])
+\end{lstlisting}
+After you told \autoconf which files to create you have to actually
+trigger their creation with command \texttt{AC\_OUTPUT}.
+
+\subsection{Using configuration information provided by configure}
+
+The \lstinline!./configure! script in the module produces a file
+\lstinline!config.h!\ that contains information about the configuration
+parameters, for example which of the optional grid implementations is
+available and which dimension has been selected (if applicable). This
+information can then be used at compile-time to include header files
+or code that depend on optional packages.
+
+As an example, the macro \lstinline!HAVE_ARRAY!\ can be used to compile
+code using C++11 arrays as in
+\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
+#ifdef HAVE_ARRAY
+#include <array>
+std::array <int, 5> a = {1, 2, 3};
+#endif
+\end{lstlisting}
+
+In some cases the macro \lstinline!HAVE_<lib>!\ is set to
+\lstinline!ENABLE_<lib>!. In this case \lstinline!ENABLE_<lib>! is
+supposed to be either \texttt{false} or \texttt{true}. It might be
+undefined which is equivalent to \texttt{false}. Thus the correct usage
+is \lstinline!#if HAVE_<lib>!\ instead of \lstinline!#ifdef HAVE_<lib>!.
+The macro \lstinline!ENABLE_<lib>!\ is not intended for the user. It
+is a trick to move the final definition of \lstinline!HAVE_<lib>!\
+to the command line.
+
+As an example, the macro \lstinline!HAVE_UG!\ can be used to compile
+UG-specific code as in
+\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
+#if HAVE_UG
+#include <dune/grid/uggrid.hh>
+#endif
+\end{lstlisting}
+
+It is important that the file \lstinline!config.h! is the first
+included header in your application!
+
+
+
+
+\subsection{dune-autogen}
+\label{autogen}
+
+The \autogen script is used to bring the freshly checked out module
+into that state that you expect from a module received via the
+tarball. That means it runs all necessary steps so that you can call
+\configure to setup your module. In the case of \dune this means that
+\autogen runs
+\begin{itemize}
+\item \texttt{libtoolize} (prepare the module for \libtool)
+\item \texttt{dunecontrol m4create} (create an m4 file containing the
+ dependencies of this module)
+\item \texttt{aclocal} (collect all \autoconf macros needed for this module)
+\item \texttt{autoheader} (create the \texttt{config.h.in})
+\item \texttt{automake} (create the \makefilein)
+\item \texttt{autoconf} (create \configure)
+\end{itemize}
+
+If needed it will also create the symbolic link to the
+\texttt{dune-common/am/} directory (see~\ref{am_includes}).
+
+\subsection{m4 files}
+\label{m4files}
+
+\texttt{m4/} files contain macros which are then composed into
+\configure and are run during execution of \configure.
+
+\minisec{private m4 macros}
+
+You can add new tests to configure by providing additional macro files
+in the directory \texttt{module/m4/}.
+
+\minisec{dependencies.m4}
+
+\texttt{\topsrc/dependencies.m4} hold all information about the
+dependencies and suggestions of this module. It is an automatically
+generated file. It is generated by \texttt{dunecontrol m4create}.
+
+\minisec{m4 module checks}
+For each dependencies of your module \texttt{\emph{MODULE}\_CHECKS}
+and \texttt{\emph{MODULE}\_CHECK\_MODULE} is called. Last
+\texttt{\emph{MODULE}\_CHECKS} is called for your module, in order to
+check all prerequisites for your module.
+
+When you have to provide the two macros
+\texttt{\emph{MODULE}\_CHECKS} and
+\texttt{\emph{MODULE}\_CHECK\_MODULE} for your module these should be
+written to a \texttt{m4/*.m4} file.
+
+Here follows an example for the module \texttt{dune-foo}:
+
+\begin{lstlisting}
+dnl -*- autoconf -*-
+# Macros needed to find dune-foo and dependent libraries. They are
+# called by the macros in ${top_src_dir}/dependencies.m4, which is
+# generated by "dunecontrol autogen"
+
+# Additional checks needed to build dune-foo
+# This macro should be invoked by every module which depends on
+# dune-foo, as well as by dune-foo itself
+AC_DEFUN([DUNE_FOO_CHECKS])
+
+# Additional checks needed to find dune-foo
+# This macro should be invoked by every module which depends on dune-foo, but
+# _not_ by dune-foo itself
+AC_DEFUN([DUNE_FOO_CHECK_MODULE],[
+ DUNE_CHECK_MODULES([dune-foo], dnl module name
+ [foo/foo.hh], dnl header file
+ [Dune::FooFnkt]) dnl symbol in libdunefoo
+])
+\end{lstlisting}
+
+The first one calls all checks required to make use of
+\texttt{dune-foo}. The dependency checks are not to be included, they
+are run automatically. The second macro tells how to check for your
+module. In case you are only writing an application and don't want to
+make this module available to other modules, you can just leave it
+empty. If you have to provide some way to find your module. The
+easiest is to use the \texttt{DUNE\_CHECK\_MODULES} macro, which is
+defined in \texttt{dune-common/m4/dune.m4}.
+
+\section{Building Sets of Modules Using \dunecontrol}
+\label{dunecontrol}
+\dunecontrol helps you building the different \dune modules in the
+appropriate order. Each module has a \dunemodule file which contains
+information on the module needed by \dunecontrol.
+
+\dunecontrol searches for \dunemodule files recursively from where you
+are executing the program. For each \dune module found it will execute
+a \dunecontrol command. All commands offered by \dunecontrol have a
+default implementation. This default implementation can be overwritten
+and extended in the \dunemodule file.
+
+The commands you are interested in right now are
+\begin{itemize}
+\item \texttt{autogen} runs \autogen for each module. A list of
+ directories containing \dunemodule files and the parameters given on
+ the command line are passed as parameters to \autogen.
+\item \texttt{configure} runs \configure for each
+ module. \texttt{--with-dune-\textit{module}} parameters are created
+ for a set of known \dune modules.
+\item \texttt{make} runs \make for each module.
+\item \texttt{all} runs \autogen, \configure and \make for each module.
+\end{itemize}
+
+In order to build \dune the first time you will need the \texttt{all}
+command. In pseudo code \texttt{all} does the following:
+\begin{lstlisting}[language=Perl]
+foreach ($module in $Modules) {
+ foreach (command in {autogen,configure,make) {
+ run $command in $module
+ }
+}
+\end{lstlisting}
+
+This differs from calling
+\begin{lstlisting}
+dunecontrol autogen
+dunecontrol configure
+dunecontrol make
+\end{lstlisting}
+as it ensures that i.e. \dunecommon is fully built before \configure
+is executed in \dunegrid. Otherwise \configure in \dunegrid would
+complain that \texttt{libcommon.la} from \dunecommon is missing.
+
+Further more you can add parameters to the commands; these parameters
+get passed on to the program being executed. Assuming you want to call
+\texttt{make clean} in all \dune modules you can execute
+\begin{lstlisting}
+dunecontrol make clean
+\end{lstlisting}
+
+\minisec{opts files}
+You can also let \dunecontrol read the command parameters from a file.
+For each command you can specify parameters. The parameters are stored
+in a variable called \texttt{\textit{COMMAND}\,\_FLAGS} with
+\texttt{\textit{COMMAND}} written in capital letters.
+
+\begin{lst}[File example.opts] \mbox{}
+\lstinputlisting{../example.opts}
+\end{lst}
+
+When you specify an opts file and command line parameters
+\begin{lstlisting}
+dunecontrol --opts=some.opts configure --with-foo=bar
+\end{lstlisting}
+\dunecontrol will ignore the parameters specified in the opts file and
+you will get a warning.
+
+\minisec{environment variables}
+You can further control the behavior of \dunecontrol by certain
+environment variables.
+\begin{itemize}
+\item \texttt{DUNE\_CONTROL\_PATH} specifies the paths, where
+ \dunecontrol is searching for modules. All entries have to be colon
+ separated and should point to either a directory (which is search
+ recursively for \texttt{dune.module} files) or a directly
+ \texttt{dune.module} file.
+\item \texttt{DUNE\_OPTS\_FILE} specifies the opts file that should be
+ read by \dunecontrol. This variable will be overwritten by the
+ \texttt{--opts=} option.
+\item \texttt{MAKE} tells \dunecontrol which command to invoke for
+ 'make'. This can be useful for example, if you want to use
+ \texttt{\textit{gmake}} as a make drop-in.
+\item \texttt{GREP} tells \dunecontrol which command to invoke for 'grep'.
+\end{itemize}
+
+\minisec{opts file variables}
+Certain aspects of the build system can be specified via additional
+entries in the opts file:
+
+\begin{itemize}
+\item \texttt{DUNE\_CONTROL\_PATH} -- see \emph{environment variables}
+\item \texttt{RESUME\_FILE} -- see \emph{Resume build after error}
+ Section \ref{sec:timesaving}
+\item \texttt{BUILDDIR} configure the modules to use out-of-source
+ build. The binaries are built in subdirectories of each module,
+ named according to the \texttt{BUILDDIR} variable.
+\item \texttt{\textit{COMMAND}\,\_FLAGS}\\ the most important ones are:
+ \begin{itemize}
+ \item \texttt{AUTOGEN\_FLAGS} specifies options for the
+ \texttt{dune-autogen} script. This allows to set\\
+ \texttt{--acversion=VERSION} or \texttt{--amversion=VERSION} to
+ force usage of a specific\\ \texttt{autoconf\$VERSION} or
+ \texttt{automake\$VERSION}.
+ \item \texttt{CONFIGURE\_FLAGS} specifies options you want to pass to
+ configure. For a list of possible parameters see
+ \texttt{./configure --help} (note that this command is only
+ available after running \texttt{dunecontrol autogen}).
+ \item \texttt{MAKE\_FLAGS} specifies options for the \texttt{make}
+ command, e.g. \texttt{-j4} to allow four concurrent build jobs.
+ \end{itemize}
+\end{itemize}
+
+\subsection{dune.module}\label{subsec::dune.module}
+
+The \dunemodule file is split into two parts. First we have the
+parameter section where you specify parameters describing the module.
+Then we have the command section where you can overload the default
+implementation of a command called via \dunecontrol.
+
+\begin{lst}[File dune.module] \mbox{}
+\begin{lstlisting}
+# parameters for dune control
+Module: dune-grid
+Version: 2.2-svn
+Maintainer: dune@dune-project.org
+Depends: dune-common (>= 2.2) dune-geometry (>= 2.2)
+Extra-Suggests: UG Alberta Alu3d
+
+# overload the run_configure command
+run_configure () {
+ # lets extend the parameter list $CMD_FLAGS
+ if test "x$HAVE_UG" == "xyes"; then
+ CMD_FLAGS="$CMD_FLAGS \"--with-ug=$PATH_UG\""
+ fi
+ if test "x$HAVE_Alberta" == "xyes"; then
+ CMD_FLAGS="$CMD_FLAGS \"--with-alberta=$PATH_Alberta\""
+ fi
+ if test "x$HAVE_Alu3d" == "xyes"; then
+ CMD_FLAGS="$CMD_FLAGS \"--with-alugrid=$PATH_Alu3d\""
+ fi
+ # call the default implementation
+ run_default_configure
+}
+\end{lstlisting}
+\end{lst}
+
+The parameter section will be parsed by \dunecontrol will effect
+i.e. the order in which the modules are built. The parameters and
+their values are separated by colon. Possible parameters are
+\begin{itemize}
+\item \texttt{Module} (\em required\em) is the name of the module. The
+ name is of the form \texttt{[a-zA-Z0-9\_-]+}.
+\item \texttt{Version} (\em optional\em) is the module's version.
+\item \texttt{Maintainer} (\em optional\em) is the email address of the
+ module's maintainer.
+\item \texttt{Depends} (\em required\em) takes a space separated list
+ of required modules. This module is not functional without these
+ other modules. Checks whether the demanded version of the required
+ modules is provided.
+\item \texttt{Suggests} (\em optional\em) takes a space separated list
+ of optional modules. This module is functional without these
+ other modules, but can offer further functionality if one or more of
+ the suggested modules are found.
+\end{itemize}
+
+The command section lets you overload the default implementation
+provided by \dunecontrol. For each command \dunecontrol call the
+function \texttt{run\_\textit{command}}. The parameters from the
+command line or the opts file are store in the variable
+\texttt{\$CMD\_FLAGS}. If you just want to create additional parameters
+you can add these to \texttt{\$CMD\_FLAGS} and then call the default
+implementation of the command via
+\texttt{run\_default\_\textit{command}}.
+
+\subsection{\dune-specific conditional builds}
+
+The \texttt{Suggests} parameter in the \texttt{dune.module} file,
+see \ref{subsec::dune.module}, gives you the flexibility to optionally build
+parts of your code depending on whether certain \dune or external modules are
+installed or not. As an example, we show in this section a \dune module with suggestions
+for the modules \texttt{dune-localfunctions} and \texttt{dune-pdelab}.
+A subdirectory \texttt{my\_pdelab\_application} should only be built if these optional modules
+are installed. We assume that your project is set up in the traditional
+\texttt{automake} fashion, i.e. there is a \texttt{Makefile.am} in every subdirectory.
+
+Suppose your \texttt{dune.module} file has dependencies on \texttt{dune-localfunctions}
+and \texttt{dune-pdelab} specified in the \texttt{Suggests} section:
+\begin{lstlisting}[language=make]
+# in the dune.module file
+Module: my_application
+Depends: dune-common dune-grid dune-istl
+Suggests: dune-localfunctions dune-pdelab
+\end{lstlisting}
+There are three steps to take now:
+\begin{enumerate}
+ \item Call \texttt{DUNE\_CHECK\_MODULES} from your local \texttt{\textit{MODULE}\_CHECK\_MODULE}
+ macro to implicitly define an \texttt{AM\_CONDITIONAL}.
+ \item This conditional can be used in any \texttt{Makefile.am} for optional builds.
+ \item The Makefile in any optional sub-directory to be build has to be
+ specified in \texttt{configure.ac} to be created.
+\end{enumerate}
+
+\minisec{The automake conditional}
+If you call the macro \texttt{DUNE\_CHECK\_MODULES} during your build process,
+an \texttt{AM\_CONDITIONAL} named \texttt{HAVE\_\textit{SUGGESTEDMODULE}} is defined where
+\texttt{\textit{SUGGESTEDMODULE}} is the name of the suggested module in upper case, and
+with any \texttt{-} replaced by \texttt{\_}. For example, for \texttt{dune-pdelab} the
+name would be \texttt{HAVE\_DUNE\_PDELAB}. \texttt{DUNE\_CHECK\_MODULES}
+is defined in \texttt{dune-common/m4/dune.m4}, and it is documented there.
+You should not call \texttt{DUNE\_CHECK\_MODULES} directly but in your local
+\texttt{m4} file in your module where your module's checks are defined,
+see section \ref{m4files}. For instance, if your module is \texttt{dune-foo},
+this call in a file \texttt{dune-foo/m4/dune-foo.m4} would be
+\begin{lstlisting}[language=make]
+AC_DEFUN([DUNE_FOO_CHECK_MODULE],
+[
+ DUNE_CHECK_MODULES([dune-foo], [foo/foo.hh])
+])
+\end{lstlisting}
+This way, the requested \texttt{AM\_CONDITIONAL} is created implicitly.
+
+\minisec{The Makefile.am clause}
+Having the \texttt{AM\_CONDITIONAL} named \texttt{HAVE\_DUNE\_PDELAB}
+defined, you can use it in any \texttt{Makefile.am} of your project
+to optionally build subdirectories or applications using \texttt{dune-pdelab}:
+\begin{lstlisting}[language=make]
+# build the directory my_pdelab_application if dune-pdelab is installed
+SUBDIRS = appl1 appl2
+if HAVE_DUNE_PDELAB
+ SUBDIRS += my_pdelab_application
+endif
+\end{lstlisting}
+Compare this \dune-specific conditional build to general conditional builds in
+Section~\ref{makefile.am}.
+
+\minisec{The configure.ac entry}
+Additionally, you have to specify in your \texttt{configure.ac}
+(section \ref{configure.ac}) that the makefile in the directory
+\texttt{my\_pdelab\_application} should be built:
+\begin{lstlisting}[language=make]
+AC_CONFIG_FILES([Makefile
+ ...
+ my_pdelab_application/Makefile
+ ...
+ dune-common.pc])
+AC_OUTPUT
+\end{lstlisting}
+Now, your project is prepared to build the subdirectory
+\texttt{my\_pdelab\_application} if and only if your machine has a successfully
+installed \texttt{dune-pdelab}.
+
+\subsection{Time savings using \dunecontrol}
+\label{sec:timesaving}
+
+\dunecontrol can help working with a growing stack of depending \dune modules and
+might save you time.
+
+\minisec{Narrow down \dune modules to apply actions to}
+Often you don't want to let \dunecontrol apply actions for every module but only
+the one you are working on.
+
+With the flag \texttt{--only=dune-foo} in
+\begin{lstlisting}[language=make]
+./dune-common/bin/dunecontrol --module=dune-foo --opts=config.opts configure
+\end{lstlisting}
+only the module \texttt{dune-foo} will be configured by \dunecontrol.
+
+Using the flag \texttt{--current} below a module's root directory \dunecontrol
+applies actions only for this module.
+
+To apply the actions to a module and all modules it depends on, set the flag
+\texttt{--module=dune-foo}.
+
+\minisec{Updates from revision control systems}
+If modules are kept in a revision control system you need to stay up to
+date and download the newest versions for your modules. The command \texttt{update}
+as in
+\begin{lstlisting}[language=make]
+./dune-common/bin/dunecontrol update
+\end{lstlisting}
+makes \dunecontrol to update every module. Currently supported and automatically detected
+revision control systems are the Concurrent Versions System (CVS), Apache
+Subversion (SVN) and Git.
+
+\minisec{Execute commands for every module}
+The \dunecontrol command \texttt{exec} allows to execute commands in the root
+directory of every module. For example the
+statement
+\begin{lstlisting}[language=make,showstringspaces=false]
+./dune-common/bin/dunecontrol exec "svn log -l10"
+\end{lstlisting}
+shows the last ten Subversion commit messages for all modules. If a module is
+not under Subversion version control the command execution fails and \dunecontrol
+stops.
+
+\minisec{Resume build after error}
+\dunecontrol stops whenever an error occurs. But you can resume from the module which
+failed. To enable this feature, you have to specify the path of a resume file in the
+variable \texttt{RESUME\_FILE} of your options file and use the flag \texttt{--resume}.
+If \dunecontrol fails it saves the name of the failing module in the specified file.
+On the next run it recognizes the failed run and resumes from the failed module on.
+
+\dunecontrol skips the first module -- the one with the error in the last run -- after
+resuming if the flag \texttt{--skipfirst} is given together with \texttt{--resume}.
+
+\minisec{Use configure caching}
+\configure is run for every module thus many tests are unnecessarily run multiple times.
+You can use \autoconf's ability to cache test results. If you add
+\texttt{--cache-file=/tmp/dune-config.cache} to the \texttt{CONFIUGURE\_FLAGS} of
+you options file the \configure cache is created. Be aware that the file persists
+between \dunecontrol runs. If you encounter any problems, you want to change the
+configuration or to rerun all checks, the cache file should be removed manually.
+
+\minisec{Faster module search}
+If the environment variable \texttt{DUNE\_CONTROL\_PATH} is not set, \dunecontrol
+recursively searches for \dune modules below the working directory. Depending on
+your installation, this search may take quite a bit of time. It can be
+avoided by including the paths to the \texttt{dune.module} files of all modules in
+\texttt{DUNE\_CONTROL\_PATH}.
+
+This list of paths can actually be created on the fly by a command.
+Let us assume all \dune modules are in one directory, which is the working directory
+for \dunecontrol, too. By adding the line
+\begin{lstlisting}[language=make,showstringspaces=false]
+DUNE_CONTROL_PATH="`ls */dune.module | tr '\n' ':'`"
+\end{lstlisting}
+to your opts file, no search will be performed. Instead, only the faster, non-recursive
+\texttt{ls} command is called.
+
+\section{Further documentation}
+
+\minisec{automake \& Makefile.am}
+\url{http://www.gnu.org/software/automake/manual/}\\
+The \automake manual describes in detail how to write and maintain a
+\makefileam and the usage of \automake.
+
+\minisec{autoconf \& configure.ac}
+\url{http://www.gnu.org/software/autoconf/manual/}\\
+The \autoconf manual covers the usage of \autoconf and how to write
+\configure.ac files (sometimes they are called \texttt{configure.in}).
+
+\minisec{Autoconf Macro Archive}
+\url{http://autoconf-archive.cryp.to/}\\
+The Autoconf Macro Archive provides macros that can be integrated in
+your \configureac in order to search for certain software. These
+macros are useful to many software writers using the autoconf tool, but too
+specific to be included into autoconf itself.
+
+\minisec{doxygen}
+\url{http://www.doxygen.org/}\\
+The \texttt{doxygen} website offers documentation on how to document
+your source code and also on the configuration parameters in your
+\texttt{Doxylocal} file.
+
+\minisec{libtool}
+\url{http://www.gnu.org/software/libtool/manual.html}\\
+The \libtool manual offers further information on the usage of
+\libtool package and gives a good overview of the different
+problems/aspects of creating portable libraries.
+
+\minisec{autobook}
+\url{http://sources.redhat.com/autobook/}\\
+The autobook is a complete book describing the GNU toolchain
+(\autoconf, \automake and \libtool). It contains many recipes on how
+to use the autotools. The book is available as an online
+version.
+
+\minisec{dune-project}
+\url{http://www.dune-project.org/}\\
+The official homepage of \dune.
+
+\end{document}
+
+%%% Local IspellDict: "american"
+%%% Local Variables:
+%%% mode: latex
+%%% TeX-master: t
+%%% End:
--- /dev/null
+.deps
+Makefile.in
+Makefile
+communication.aux
+communication.bbl
+communication.blg
+communication.log
+communication.out
+communication.pdf
+communication.toc
+indexset
+poosc08
+poosc08_test
--- /dev/null
+add_executable(poosc08 "poosc08.cc")
+target_link_libraries(poosc08 "dunecommon")
+add_executable(poosc08_test "poosc08_test.cc")
+target_link_libraries(poosc08_test "dunecommon")
+add_executable(indexset "indexset.cc")
+target_link_libraries(indexset "dunecommon")
+add_dune_mpi_flags("poosc08;poosc08_test;indexset")
+dune_add_latex_document(communication.tex FATHER_TARGET doc
+ BIBFILES communication.bib DEFAULT_SAFEPDF INPUTS poosc08_test.cc
+ IMAGE_DIRS figures)
+create_doc_install(${CMAKE_CURRENT_BINARY_DIR}/communication.pdf ${CMAKE_INSTALL_DOCDIR}/comm communication_safepdf)
--- /dev/null
+# $Id: Makefile.am 1681 2012-08-31 11:30:17Z gruenich $
+
+SUBDIRS = figures
+
+MPIPROGRAMS = indexset poosc08 poosc08_test
+
+EXTRA_DIST = CMakeLists.txt
+
+# programs just to build when "make check" is used
+check_PROGRAMS = $(MPIPROGRAMS)
+# list of tests to run (indicestest is special case)
+TESTS = $(MPIPROGRAMS)
+
+if BUILD_DOCS
+ DOCFILES = communication.pdf
+ EXTRA_DIST += $(DOCFILES)
+ EXTRAINSTALL = $(DOCFILES)
+endif
+
+# setting like in dune-web
+CURDIR=doc/comm
+BASEDIR=../../..
+
+# install the docs
+docdir=$(datadir)/doc/dune-common/comm
+
+include $(top_srcdir)/am/latex
+include $(top_srcdir)/am/webstuff
+include $(top_srcdir)/am/global-rules
+
+poosc08_SOURCES = poosc08.cc
+poosc08_CPPFLAGS = $(AM_CPPFLAGS) \
+ $(DUNEMPICPPFLAGS)
+poosc08_LDFLAGS = $(AM_LDFLAGS) \
+ $(DUNEMPILDFLAGS)
+poosc08_LDADD = \
+ $(DUNEMPILIBS) \
+ $(LDADD)
+
+poosc08_test_SOURCES = poosc08_test.cc
+poosc08_test_CPPFLAGS = $(AM_CPPFLAGS) \
+ $(DUNEMPICPPFLAGS)
+poosc08_test_LDFLAGS = $(AM_LDFLAGS) \
+ $(DUNEMPILDFLAGS)
+poosc08_test_LDADD = \
+ $(DUNEMPILIBS) \
+ $(LDADD)
+
+indexset_SOURCES = indexset.cc buildindexset.hh reverse.hh
+indexset_CPPFLAGS = $(AM_CPPFLAGS) \
+ $(DUNEMPICPPFLAGS)
+indexset_LDFLAGS = $(AM_LDFLAGS) \
+ $(DUNEMPILDFLAGS)
+indexset_LDADD = \
+ $(DUNEMPILIBS) \
+ $(LDADD)
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id: buildindexset.hh 1565 2012-04-30 22:04:34Z mblatt $
+#ifndef BUILDINDEXSET_HH
+#define BUILDINDEXSET_HH
+
+
+#include <dune/common/parallel/indexset.hh>
+#include <dune/common/parallel/plocalindex.hh>
+
+/**
+ * @brief Flag for marking the indices.
+ */
+enum Flag {owner, overlap};
+
+// The type of local index we use
+typedef Dune::ParallelLocalIndex<Flag> LocalIndex;
+
+/**
+ * @brief Add indices to the example index set.
+ * @param indexSet The index set to build.
+ */
+template<class C, class TG, int N>
+void build(C& comm, Dune::ParallelIndexSet<TG,LocalIndex,N>& indexSet)
+{
+
+
+
+
+ // The rank of our process
+ int rank=comm.rank();
+
+ // Indicate that we add or remove indices.
+ indexSet.beginResize();
+
+ if(rank==0) {
+ indexSet.add(0, LocalIndex(0,overlap,true));
+ indexSet.add(2, LocalIndex(1,owner,true));
+ indexSet.add(6, LocalIndex(2,owner,true));
+ indexSet.add(3, LocalIndex(3,owner,true));
+ indexSet.add(5, LocalIndex(4,owner,true));
+ }
+
+ if(rank==1) {
+ indexSet.add(0, LocalIndex(0,owner,true));
+ indexSet.add(1, LocalIndex(1,owner,true));
+ indexSet.add(7, LocalIndex(2,owner,true));
+ indexSet.add(5, LocalIndex(3,overlap,true));
+ indexSet.add(4, LocalIndex(4,owner,true));
+ }
+
+ // Modification is over
+ indexSet.endResize();
+}
+#endif
--- /dev/null
+@InProceedings{ISTL,
+ author = {Markus Blatt and Peter Bastian},
+ title = {The Iterative Solver Template Library},
+ booktitle = {Applied Parallel Computing. State of the Art in Scientific Computing},
+ editor = {Bo K\r{a}gstr\"om and Erik Elmroth and Jack Dongarra and Jerzy Wa\'sniewski},
+ year = 2007,
+ volume = 4699,
+ series = {Lecture Notes in Computer Science},
+ publisher = {Springer},
+ pages = {666--675}
+}
+
+@Article{dune08-1,
+ author = {Peter Bastian and Markus Blatt and Andreas Dedner and Christian Engwer and Robert Kl\"ofkorn and Mario Ohlberger and Oliver Sander},
+ title = { A generic grid interface for parallel and adaptive scientific computing. Part I: abstract framework},
+ journal = {Computing},
+ year = 2008,
+ volume = 82,
+ number = {2--3},
+ pages = {103--119}
+}
+@Article{dune08-2,
+ author = {Peter Bastian and Markus Blatt and Andreas Dedner and Christian Engwer and Robert Kl\"ofkorn and Ralf Kornhuber and Mario Ohlberger and Oliver Sander},
+ title = { A generic grid interface for parallel and adaptive scientific computing. Part II: implementation and test in DUNE},
+ journal = {Computing},
+ year = 2008,
+ volume = 82,
+ number = {2--3} ,
+ pages = {121--138}
+}
+@Article{ISTLParallel,
+ author = {Markus Blatt and Peter Bastian},
+ title = {On the Generic Parallelisation of Iterative Solvers for
+ the Finite Element Method},
+ journal = {Int. J. Computational Science and
+ Engineering},
+ volume = {4},
+ number = {1},
+ pages = {56--69},
+ year = 2008
+}
+
+@Misc{DuneWeb,
+ author = {DUNE},
+ howpublished = {\texttt{http://www.dune-project.org/}}
+}
+@Misc{boost_mpi,
+ author = {D. Gregor and M. Troyer},
+ title = {{B}oost.{M}{P}{I}},
+ howpublished = {\texttt{http://www.boost.org/}},
+ year = 2006
+}
+
+@PhdThesis{gerlach02:janus,
+ author = {Jens Gerlach},
+ title = {Domain Engineering and Generic Programming for Parallel Scientific Computing},
+ school = {TU Berlin},
+ year = {2002}
+}
+
+@InProceedings{giloi95:_promot,
+ author = {W.K. Giloi and M. Kessler and A. Schramm},
+ title = {PROMOTER: A High Level, Object-Parallel Programming Language},
+ booktitle = {Proceedings of the International Conference on High Performance Computing},
+ year = {1995},
+ address = {New Dehli, India},
+ month = {December}
+}
+
+@inproceedings{nolte00:_taco,
+ author = {J\"{o}rg Nolte and Mitsuhisa Sato and Yutaka Ishikawa},
+ title = {TACO -- Dynamic Distributed Collections with Templates and Topologies},
+ booktitle = {Euro-Par '00: Proceedings from the 6th International Euro-Par Conference on Parallel Processing},
+ year = {2000},
+ isbn = {3-540-67956-1},
+ pages = {1071--1080},
+ publisher = {Springer-Verlag},
+ address = {London, UK},
+ }
\ No newline at end of file
--- /dev/null
+\documentclass[11pt]{article}
+\usepackage{multicol}
+\usepackage{ifthen}
+%\usepackage{multitoc}
+%\usepackage{german}
+%\usepackage{bibgerm}
+\usepackage{amsthm}
+\usepackage{amsmath}
+\usepackage{amsfonts}
+\usepackage{color}
+\usepackage{hyperref}
+\usepackage{psfrag}
+\usepackage{subfigure}
+\usepackage[dvips]{epsfig}
+\usepackage[dvips]{graphicx}
+\usepackage[a4paper,body={148mm,240mm,nohead}]{geometry}
+\usepackage[ansinew]{inputenc}
+\usepackage{listings}
+\lstset{language=C++, basicstyle=\ttfamily,
+ stringstyle=\ttfamily, commentstyle=\it, extendedchars=true}
+
+\newif\ifpdf
+\ifnum\ifx\pdfoutput\undefined0\else\pdfoutput\fi<1
+\pdffalse % we are not running PDFLaTeX
+\else
+\pdftrue % we are running PDFLaTeX
+\fi
+
+\ifpdf
+\usepackage[pdftex]{graphicx}
+\else
+\usepackage{graphicx}
+\fi
+
+\ifpdf
+\DeclareGraphicsExtensions{.pdf, .jpg, .tif}
+\else
+\DeclareGraphicsExtensions{.eps, .jpg}
+\fi
+
+%\theoremstyle{plain}
+\newtheorem{theorem}{Theorem}[section]
+\newtheorem{lemma}[theorem]{Lemma}
+
+\theoremstyle{definition}
+\newtheorem{definition}[theorem]{Definition}
+\newtheorem{class}[theorem]{Class}
+\newtheorem{algorithm}[theorem]{Algorithm}
+\theoremstyle{remark}
+\newtheorem{remark}[theorem]{Remark}
+
+\newcommand{\C}{\mathbb{C}}
+\newcommand{\R}{\mathbb{R}}
+\newcommand{\N}{\mathbb{N}}
+\newcommand{\Z}{\mathbb{Z}}
+\newcommand{\Q}{\mathbb{Q}}
+\newcommand{\K}{\mathbb{K}}
+\newcommand{\loc}{\mbox{loc}}
+
+\title{Communication within the Iterative Solver Template Library (ISTL)\thanks{Part of the
+ Distributed and Unified Numerics Environment (DUNE) which is
+ available from the site
+ \texttt{http://www.dune-project.org/}}}
+
+\author{%
+Markus Blatt\\
+Interdisziplinäres Zentrum für Wissenschaftliches Rechnen,\\
+Universität Heidelberg, Im Neuenheimer Feld 368, D-69120 Heidelberg, \\
+email: \texttt{Markus.Blatt@iwr.uni-heidelberg.de}}
+
+\date{April 27, 2005}
+
+\begin{document}
+
+\maketitle
+
+\begin{abstract}
+ This document describes usage and interface of the classes meant for
+ setting up the communication within a parallel programm using
+ ISTL. As most of the communication in distributed programm occur in
+ the same pattern it is often more efficient (and of course more easy
+ for the programmer) to build the communication pattern once in the
+ programm and then use multiple times (e.~g. at each iteration step
+ of an iterative solver).
+\end{abstract}
+
+\begin{multicols}{2}
+{\small\tableofcontents}
+\end{multicols}
+
+
+\section{Introduction}
+\label{sec:introduction}
+
+When using the data parallel programming model a set of processes
+works collectively on the same set of finite data objects. These might
+be elements of a finite element grid or vector entries in a linear algebra
+computation. Each process works on different partitions of the global
+data. Only for this partition it computes updated values.
+
+In large scale parallel codes it is advisable to store the data
+partition in a local data structure directly in the local memory of
+the process. Due to data dependencies the process needs to access data
+in the partition of other processes, too. This can either be done by
+communicating these values on demand between the processes whenever
+they are accessed. This results in data structures that are aware of
+the data distribution. Or by augmenting the partition of the process such
+that it additionally includes the data values that the other values
+depend on. Note that now the partitioning is not disjoint any more but
+overlapping. Of course the values other processes compute for need to
+be updated using communication at so called synchronisation points of
+the algorithm
+
+In the latter case the data structures do not need to know anything
+about the data distribution.
+This demands more effort from the parallel algorithm designer to make
+sure that the data used for computations is valid, i.e. contains an
+updated value if another process computes the data for it. Still it allows
+for fewer synchronisation points in the algorithms as even in collective
+operations all input data may already be updated from other processes
+due to a previous operation. Between the necessary synchronisation
+points one can take advantage of the fast local memory
+access.
+
+Consider representing a random access container $x$ on a set of
+processes ${\cal P}=\{0, \ldots, P-1\}$. It is represented by individual
+pieces $x^p$, where $x^p$ is the piece stored on
+process $p$ of the $P$ processes participating in the
+calculation. Although the global representation of the container is
+not available on any process, a process $p$ needs to know how the
+entries of its local piece $x^p$ correspond to the entries of the
+global container $x$, which would be used in a sequential program.
+
+\section{Communication Software Components}
+\label{sec:comm-softw-comp}
+
+From an abstract point of view a random access container $x: I
+\rightarrow K$ provides a
+mapping from an index set $I \subset \N_0$ onto a set of objects
+$K$. Note that we do not require $I$ to be consecutive. The piece
+$x_p$ of the container $x$ stored on process $p$ is a mapping $x_p:I_p
+\rightarrow K$, where $I_p \subset I$. Due to efficiency the entries
+of $x_p$ should be stored consecutively in memory.
+This means that for the local computation the data must be addressable
+by a consecutive index starting from $0$.
+
+When using adaptive
+discretisation methods there might be the need to reorder the indices
+after adding and/or deleting some of the discretisation
+points. Therefore this index does not need to be persistent
+and can easily be changed. We will call this index {\em\index{local index}local index}.
+
+For the communication phases of our algorithms these locally stored
+entries must also be addressable by a global identifier. It is used to
+store the received values at and to retrieve the values to be sent from the
+correct local position in the consecutive memory chunk. To ease the
+addition and removal of discretisation points this global identifier has
+to be persistent but does not need to be consecutive. We
+will call this global identifier {\em\index{global index}global index}.
+
+\subsection{ParallelIndexSet}
+ Let $I \subset \N_0$ be an arbitrary, not necessarily consecutive,
+ index set identifying all discretisation points of the computation.
+ Furthermore, let
+ $$({I}_p)_{p\in {\cal P}}, \quad
+ \bigcup\limits_{p \in {\cal P}} {I}_p = I$$ be an overlapping decomposition of the global index set
+ $I$ into the sets of indices ${I}_p$ corresponding to the
+ global indices of the values stored locally in the chunk of process $p$.
+
+ Then the class
+ \begin{lstlisting}{}
+ template<typename TG, typename TL> class ParallelIndexSet;
+ \end{lstlisting}
+ realises the one to one mapping
+ $$
+ \gamma_p\::\: {I}_p \longrightarrow {I}^{\loc}_p := [0, n_p)
+ $$
+ of the globally unique index onto the local index.
+
+ The template parameter \lstinline!TG! is the type of the global
+ index and
+ \lstinline!TL! is the type of the local index. The only prerequisite
+ of \lstinline!TG! is that objects of this type are comparable using
+ the less-than-operator \lstinline!<!. Not that this prerequisite
+ still allows attaching further
+ information to the global index or even using this information as
+ the global index. The type \lstinline!TL! has to
+ be convertible to \lstinline!std::size_t! as it is used to address array
+ elements.
+
+ The pairs of global and local indices are
+ ordered by ascending global index. It is possible to access the pairs via
+\lstinline!operator[](TG& global)! in $log(n)$ time, where $n$ is the
+number of pairs in the set. In an efficient code it is advisable to
+access the index pairs using the provided iterators over the index pairs.
+
+Due to the ordering, the index set can only be changed, i.e. index pairs
+added or deleted, in a special resize phase. By calling the functions
+\lstinline!beginResize()! and \lstinline!endResize()! the programmer
+indicates that the resize phase starts and ends, respectively. During
+the call of \lstinline!endResize()! the deleted indices will be
+removed and the added index pairs will be sorted and merged with the existing
+ones.
+
+\subsection{ParallelLocalIndex}
+When dealing with overlapping index sets in distributed computing
+there often is the need to distinguish different partitions of an index
+set.%, e.g. $I_i$ and $\tilde{I}_i\setminus I_i$ as introduced in Section \ref{sec:domain_decomposition}.
+
+This is accomplished by using the class
+\begin{lstlisting}{}
+ template<typename TA> class ParallelLocalIndex;
+\end{lstlisting}
+as the type for the local index of class \lstinline!ParallelIndexSet!.
+Here the template parameter \lstinline!TA! is the type of the
+attributes used, e.g. an enumeration \lstinline!Flags! defined by
+\begin{lstlisting}
+ enum Flags {owner, ghost};
+\end{lstlisting}
+where
+\lstinline!owner! marks the indices $k \in I_p$ owned by process
+$p$ and \lstinline!ghost! the indices $k\not\in I_p$ owned
+by other processes.
+
+As an example let us look at an array distributed between two
+processes. In Figure \ref{fig:redistarray} one can see the array
+$a$ as it appears in a sequential program. Below there are two
+different distributions of that array. The local views $s_0$ and
+$s_1$ are the parts process $0$ and $1$ store in the case that $a$ is
+divided into two
+blocks. The local views $t_0$ and $t_1$ are the parts of $a$ that
+process $0$ and $1$ store in the case that $a$ is divided into 4
+blocks and process
+$0$ stores the first and third block and process $1$ the second and
+fourth block. The decompositions have an overlap of one and the indices have
+the attributes \lstinline!owner! and \lstinline!ghost! visualised by
+white and shaded cells, respectively.
+The index sets $I_s$ and $I_t$ corresponding to the decompositions $s_p$
+and $t_p$, $p \in \{0,1\}$, are shown in Figure \ref{fig:redistindex} as sets of triples
+$(g,l,a)$. Here $g$ is the global index, $l$ is the local index and
+$a$ is the attribute (either o for \lstinline!owner! or {g}
+for \lstinline!ghost!).
+\begin{figure}%[b]
+ \centering
+ \psfrag{Is}{$I_s$}
+ \psfrag{It}{$I_t$}
+ \epsfig{file=figures/distindex.eps,width=.5\textwidth}
+ \caption{Index sets for array redistribution}
+ \label{fig:redistindex}
+\end{figure}
+\begin{figure*}%[b]
+ \centering
+ \psfrag{a0:}{$s_0$:}
+ \psfrag{a1:}{$s_1$:}
+ \psfrag{b0:}{$t_0$:}
+ \psfrag{b1:}{$t_1$:}
+ \epsfig{file=figures/distarray.eps,width=.9\textwidth}
+ \caption{Redistributed array}
+ \label{fig:redistarray}
+\end{figure*}
+
+The following code snippet demonstrates how to set up the index set
+$I_s$ on process $0$:
+\lstinputlisting[linerange={53-57,59-61,67-67}]{poosc08_test.cc}
+\subsection{Remote Indices}
+\label{sec:remote-indices}
+
+To set up communication between the processes every process needs to
+know which indices are also known to other processes and which
+attributes are attached to them on the remote side.
+There are scenarios where data is exchanged between different
+index sets, e.g. if the data is agglomerated on lesser processes or
+redistributed. Therefore communication is allowed to occur between different
+decompositions of the same index set.
+
+
+Let $I \subset \N$ be the global index set and
+$$
+(I^s_p)_{p\in{\cal P}},\quad \bigcup_{p\in{\cal P}} I^s_p = I,\quad
+\text{ and } \quad
+(I^t_p)_{p\in{\cal P}}, \quad\bigcup_{p\in{\cal P}} I^t_p = I
+$$ be two overlapping
+decompositions of the same index set $I$. Then an instance of class
+\lstinline!RemoteIndices! on process $p \in {\cal P}$
+stores the sets of triples
+\begin{equation}
+ \label{eq:ri_s_set}
+ \begin{split}
+ r_{p \rightarrow q}^{s} = \{ (g,(l,a),b) \,|\, g \in I^s_q \wedge g \in I_p^t,
+l=\gamma_p^s(g), a = \alpha_p^s(l), b =
+\alpha_q^t(\gamma_q^t(g))\}
+\end{split}
+\end{equation}
+and
+\begin{equation}
+ \label{eq:ri_t_set}
+ \begin{split}
+ r_{p \rightarrow q}^{t} = \{ (g,(l,a),b) \,|\, g \in I^s_q \wedge g \in I_p^t,
+ l=\gamma_p^t(g), a = \alpha_p^t(l), b =
+ \alpha_p^s(\gamma_p^s(g))\}\,,
+ \end{split}
+\end{equation}
+for all $q\in{\cal P}$.
+Here $\alpha^s_p$ and $\alpha^t_p$ denote the mapping of local
+indices on process $p$ onto attributes for the index set $I^s_p$ and
+$I^t_p$ as realised by \lstinline!ParallelLocalIndex!.
+Note that the sets $r_{p \rightarrow q}^{s}$ and $r_{p \rightarrow
+ q}^{t}$ will only be nonempty if the processes $p$ and $q$ manage
+overlapping index sets.
+
+For our example in Figure \ref{fig:redistarray} and Figure
+\ref{fig:redistindex} the interface between $I_s$ and $I_t$ on process
+$0$ is:
+\begin{align*}
+ r_{0\rightarrow 0}^{s} = \{&(0,(0,o),o), (1,(1,o),o), (2,(2,o),o),
+ (3,(3,o),g), (5,(5,o),g), (6,(6,g),o)\}\\
+ r_{0\rightarrow 0}^{t} = \{&(0,(0,o),o), (1,(1,o),o), (2,(2,o),o),
+ (3,(3,g),o), (5,(4,g),o), (6,(5,o),g)\}\\
+ r_{0\rightarrow 1}^{s} = \{&(2(2,o),g), (3,(3,o),o), (4,(4,o),o),
+ (5,(5,o),o), (6,(6,g),g)\}\\
+ r_{0\rightarrow 1}^{t} = \{&(5,(4,g),g), (6,(5,o),o), (7,(6,o),o),
+ (8,(7,o),o), (9,(8,g),o)\}
+\end{align*}
+This information can either be calculated automatically by
+communicating all indices in a ring or set up by hand if the user has
+this information available. Assuming that \lstinline!sis! is the index set
+$I_s$ and \lstinline!tis! the index set $I_t$ set up as described in
+the previous subsection and \lstinline!comm! is an MPI communicator
+then the simple call
+\lstinputlisting[linerange={83-84}]{poosc08_test.cc}
+on all processes automatically calculates this information and
+stores it in \lstinline!riRedist!. For a
+parallel calculation on the local views $s_0$ and $s_1$ calling
+\lstinputlisting[linerange={86-87}]{poosc08_test.cc}
+on all processes builds the necessary information in \lstinline!riS!.
+
+\subsection{Communication Interface}
+\label{sec:comm-interf}
+
+With the information provided by class \lstinline!RemoteIndices! the
+user can set up arbitrary communication interfaces. These interfaces
+are realised in \lstinline!template<typename T> class Interface!,
+where the template parameter \lstinline!T! is the custom type of the
+\lstinline!ParallelIndexSet! representing the index sets.
+Using the attributes attached to the indices by
+\lstinline!ParallelLocalIndex! the user can select subsets of the
+indices for exchanging data, e.g. send data from indices marked
+as \lstinline!owner! to indices marked as \lstinline!ghost!.
+
+Basically the interface on process $p$ manages two sets for each
+process $q$ it shares common indices with:
+
+$$
+i_{p\rightarrow q}^{s} = \{ l | (g,(l,a),b) \in r_{p\rightarrow q}^{s} |
+a \in A_s \wedge b \in A_t\}
+$$
+and
+$$
+i_{p\rightarrow q}^{t} = \{ l | (g, (l,a), b) \in r_{p\rightarrow q}^{t} |
+a \in A_t \wedge b \in A_s\}\,,
+$$
+where $A_s$ and $A_t$ are the attributes marking the indices where the
+source and target of the communication will be, respectively.
+
+In our example these sets on process $0$ will be stored for
+communication if $A_s=\{o\}$ and $A_t=\{o, g\}$:
+\begin{align*}
+ i_{0\rightarrow 0}^{s} = \{0, 1, 3, 5\}\quad & \quad
+ i_{0\rightarrow 0}^{t} = \{0, 1, 3, 4\}\\
+ i_{0\rightarrow 1}^{s} = \{2, 3, 4, 5\}\quad & \quad
+ i_{0\rightarrow 1}^{t} = \{5, 6, 7, 8\}\,.
+\end{align*}
+
+The following code snippet would build the interface above in
+\lstinline!infRedist! as well as the interface \lstinline!infS!
+to communicate between
+indices marked as \lstinline!owner! and \lstinline!ghost! on the local
+array views $s_0$ and $s_1$:
+\lstinputlisting[linerange={89-97}]{poosc08_test.cc}
+
+\subsection{Communicator}
+\label{sec:communicator}
+
+Using the classes from the previous sections all information about the
+communication is available and we are set to communicate data values
+of arbitrary
+container types. The only prerequisite for the container type is that
+its values are addressable via \lstinline!operator[](size_t index)!.
+This should be safe to assume.
+
+An important feature of our communicators is that we are not only able to
+send one data item per index, but also different numbers of data
+elements (of the same type) for each index. This is
+supported in a generic way by the traits class
+\lstinline!template<class V> struct CommPolicy!
+describing the container type \lstinline!V!. The
+\lstinline!typedef IndexedType! is the atomic type to be communicated and
+\lstinline!typedef IndexedTypeFlag! is either \lstinline!SizeOne! if
+there is only one data item per index or \lstinline!VariableSize! if the
+number of data items per index is variable.
+
+The default implementation works for all
+array-like containers which provide only one data item per index. For all
+other containers the user has to provide its own custom
+specialisation.
+%For the vector classes of ISTL (up to two block levels)
+%those specialisations are already implemented.
+
+The class \lstinline!template<class T> class BufferedCommunicator!
+performs the
+actual communication. The template parameter \lstinline!T! describes
+the type of the parallel index set.
+It uses the information about the communication interface provided by
+an object of class \lstinline!Interface! to set up communication
+buffers for a container containing a specific data type. It is also
+responsible for gathering the data before and scattering the data
+after the communication step. The strict separation of the interface
+description from the actual buffering and communication allows for
+reusing the interface information with various different container and
+data types.
+
+Before the communication can start one has to call the
+\lstinline!build! method with the data source and target containers as
+well as the communication interface as arguments. Assuming
+\lstinline!s! and \lstinline!t! as arrays $s_i$ and $t_i$,
+respectively, then
+\lstinputlisting[linerange=103-106]{poosc08_test.cc}
+demonstrates how to set up the communicator \lstinline!bCommRedist! for the array
+redistribution and \lstinline!bComm! for a parallel calculation on the
+local views $s_i$. The
+\lstinline!build! function
+calculates the size of the messages to send to other processes and
+allocates buffers for the send and receive actions. The
+representatives \lstinline!s! and \lstinline!t! are
+needed to get the number of data values at each index in the case of
+variable numbers of data items per index. Note that, due to the generic
+programming techniques used, the compiler knows if the number of data
+points is constant for each index and will apply a specialised
+algorithm for calculating the message size without querying neither
+\lstinline!s! nor \lstinline!t!. Clean up of allocated
+resources is done either by calling the method \lstinline!free()! or
+automatically in the destructor.
+
+The actual communication takes place if one of the methods
+\lstinline!forward!
+and \lstinline!backward! is called. In our case in
+\lstinline!bCommRedist! the \lstinline!forward! method
+sends data from the local views $s_i$ to the local views $t_i$
+according to the interface information and the \lstinline!backward!
+method in the opposite direction.
+
+The following code snippet first redistributes the local views $s_i$
+of the global array to the local views $t_i$ and
+performs some calculation on this representation. Afterwards the
+result is communicated backwards.
+\lstinputlisting[linerange=110-113]{poosc08_test.cc}
+
+Note that both methods have a different template parameter, either
+\lstinline!CopyData! or \lstinline!AddData!. These are policies for
+gathering and scattering the data items. The former just copies
+the data from and to the location. The latter copies from the source
+location but adds the received data items to the target
+entries. Assuming our data is stored in simple C-arrays
+\lstinline!AddData! could be implemented like this:
+
+\lstinputlisting[linerange=16-27]{poosc08_test.cc}
+
+Note that arbitrary
+manipulations can be applied to the communicated data in both methods.
+
+For containers with multiple data items associated with one index
+the methods \lstinline!gather! and \lstinline!scatter! must have an additional
+integer argument specifying the sub-index.
+
+\section{Collective Communication}
+\label{sec:collective-communication}
+
+While communicating entries of array-like structures is a prominent
+task in scientific computing codes one must not neglect
+collective communication operations, like gathering and scattering data
+ from and to all processes, respectively, or waiting for other processes. An
+abstraction for these operations is crucial for decoupling the
+communication from the parallel programming paradigm used.
+
+Therefore we designed
+\lstinline!template<class T> class CollectiveCommunication! which provides
+information of the underlying parallel programming paradigm as well as
+the collective communication operations as known from MPI. See Table
+\ref{tab:col-comm} for a list of all functions.
+
+\begin{table*}%[b]
+ \centering
+ \begin{tabular}{p{.5\textwidth}|p{.4\textwidth}}
+ Function&Description\\\hline\hline
+ \lstinline!int rank()!&Get the rank of the process\\
+ \lstinline!int size()!&Get the number of processes\\
+ \lstinline!template<typename T> T sum (T& in)!& Compute global
+ sum\\
+ \lstinline!template<typename T> T prod (T& in)!&Compute global
+ product\\
+ \lstinline!template<typename T> T min (T& in)!&Compute global minimum\\
+ \lstinline!template<typename T> T max (T& in)!&Compute global
+ maximum\\
+ \lstinline!void barrier()!& Wait for all processes.\\
+ \lstinline!template<typename T> int broadcast (T* inout, int len, int root)!
+& Broadcast an array from root to all other processes\\
+\lstinline!template<typename T> int gather (T* in, T* out, int len, int root)!&
+Gather arrays at a root process\\
+\lstinline!template<typename BinaryFunction, typename Type> int allreduce(Type* in, Type* out, int len)!&
+Combine values from all processes on all processes. Combine function
+is given with \lstinline!BinaryFunction!
+ \end{tabular}
+ \caption{Collective Communication Functions}
+ \label{tab:col-comm}
+\end{table*}
+
+Currently there is a default implementation for sequential programs
+as well as a specialisation working with MPI. This approach allows for
+running parallel programs sequentially without any parallel overhead
+simply by choosing the sequential specialisation at compile time.
+Note that the interface is far more convenient to use than the C++
+interface of MPI. The latter is a simple wrapper around the C
+implementation without taking advantage of the power of generic programming.
+
+
+The collective communication classes were developed before the release
+of Boost.MPI \cite{boost_mpi}. In contrast to Boost.MPI it was never
+meant as a full generic implementation of all MPI functions. Instead it
+is restricted to the most basic subset of collective operations needed
+to implement finite element methods and iterative solver using the
+previously described components. This lean interface should make it
+possible to easily port this approach to
+thread based parallelisation as well as other parallelisation
+paradigms. This would allow code to easily switch between different paradigms
+
+
+\bibliographystyle{plainnat}
+\bibliography{communication}
+\end{document}
+%%% Local Variables:
+%%% mode: latex
+%%% TeX-master: t
+%%% End:
--- /dev/null
+Makefile.in
+Makefile
--- /dev/null
+# $Id: $
+EXTRA_DIST=darray.eps distarray.eps distindex.eps
+
+include $(top_srcdir)/am/webstuff
+include $(top_srcdir)/am/global-rules
--- /dev/null
+%!PS-Adobe-2.0 EPSF-2.0
+%%Title: ../eps/darray.eps
+%%Creator: fig2dev Version 3.2 Patchlevel 1
+%%CreationDate: Thu Mar 4 15:25:17 1999
+%%For: peter@speedo (Peter Bastian)
+%%Orientation: Portrait
+%%BoundingBox: 0 0 345 260
+%%Pages: 0
+%%BeginSetup
+%%EndSetup
+%%Magnification: 1.0000
+%%EndComments
+/$F2psDict 200 dict def
+$F2psDict begin
+$F2psDict /mtrx matrix put
+/col-1 {0 setgray} bind def
+/col0 {0.000 0.000 0.000 srgb} bind def
+/col1 {0.000 0.000 1.000 srgb} bind def
+/col2 {0.000 1.000 0.000 srgb} bind def
+/col3 {0.000 1.000 1.000 srgb} bind def
+/col4 {1.000 0.000 0.000 srgb} bind def
+/col5 {1.000 0.000 1.000 srgb} bind def
+/col6 {1.000 1.000 0.000 srgb} bind def
+/col7 {1.000 1.000 1.000 srgb} bind def
+/col8 {0.000 0.000 0.560 srgb} bind def
+/col9 {0.000 0.000 0.690 srgb} bind def
+/col10 {0.000 0.000 0.820 srgb} bind def
+/col11 {0.530 0.810 1.000 srgb} bind def
+/col12 {0.000 0.560 0.000 srgb} bind def
+/col13 {0.000 0.690 0.000 srgb} bind def
+/col14 {0.000 0.820 0.000 srgb} bind def
+/col15 {0.000 0.560 0.560 srgb} bind def
+/col16 {0.000 0.690 0.690 srgb} bind def
+/col17 {0.000 0.820 0.820 srgb} bind def
+/col18 {0.560 0.000 0.000 srgb} bind def
+/col19 {0.690 0.000 0.000 srgb} bind def
+/col20 {0.820 0.000 0.000 srgb} bind def
+/col21 {0.560 0.000 0.560 srgb} bind def
+/col22 {0.690 0.000 0.690 srgb} bind def
+/col23 {0.820 0.000 0.820 srgb} bind def
+/col24 {0.500 0.190 0.000 srgb} bind def
+/col25 {0.630 0.250 0.000 srgb} bind def
+/col26 {0.750 0.380 0.000 srgb} bind def
+/col27 {1.000 0.500 0.500 srgb} bind def
+/col28 {1.000 0.630 0.630 srgb} bind def
+/col29 {1.000 0.750 0.750 srgb} bind def
+/col30 {1.000 0.880 0.880 srgb} bind def
+/col31 {1.000 0.840 0.000 srgb} bind def
+
+end
+save
+-130.0 296.0 translate
+1 -1 scale
+
+/cp {closepath} bind def
+/ef {eofill} bind def
+/gr {grestore} bind def
+/gs {gsave} bind def
+/sa {save} bind def
+/rs {restore} bind def
+/l {lineto} bind def
+/m {moveto} bind def
+/rm {rmoveto} bind def
+/n {newpath} bind def
+/s {stroke} bind def
+/sh {show} bind def
+/slc {setlinecap} bind def
+/slj {setlinejoin} bind def
+/slw {setlinewidth} bind def
+/srgb {setrgbcolor} bind def
+/rot {rotate} bind def
+/sc {scale} bind def
+/sd {setdash} bind def
+/ff {findfont} bind def
+/sf {setfont} bind def
+/scf {scalefont} bind def
+/sw {stringwidth} bind def
+/tr {translate} bind def
+/tnt {dup dup currentrgbcolor
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
+ bind def
+/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
+ 4 -2 roll mul srgb} bind def
+/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
+/$F2psEnd {$F2psEnteredState restore end} def
+%%EndProlog
+
+$F2psBegin
+10 setmiterlimit
+n -1000 5689 m -1000 -1000 l 8527 -1000 l 8527 5689 l cp clip
+ 0.06299 0.06299 sc
+% Polyline
+7.500 slw
+n 5265 3105 m 7515 3105 l 7515 3780 l 5265 3780 l cp gs col0 s gr
+% Polyline
+n 5670 3105 m 5670 3780 l gs col0 s gr
+% Polyline
+n 6120 3105 m 6120 3780 l gs col0 s gr
+% Polyline
+n 6570 3105 m 6570 3780 l gs col0 s gr
+% Polyline
+n 7020 3105 m 7020 3780 l gs col0 s gr
+/Times-Roman ff 180.00 scf sf
+5400 4050 m
+gs 1 -1 sc (0) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+6300 4050 m
+gs 1 -1 sc (2) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+6750 4050 m
+gs 1 -1 sc (3) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+7245 4050 m
+gs 1 -1 sc (4) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+5850 4050 m
+gs 1 -1 sc (1) col0 sh gr
+% Polyline
+n 2340 3105 m 4590 3105 l 4590 3780 l 2340 3780 l cp gs col0 s gr
+% Polyline
+n 2745 3105 m 2745 3780 l gs col0 s gr
+% Polyline
+n 3195 3105 m 3195 3780 l gs col0 s gr
+% Polyline
+n 3645 3105 m 3645 3780 l gs col0 s gr
+% Polyline
+n 4095 3105 m 4095 3780 l gs col0 s gr
+/Times-Roman ff 180.00 scf sf
+2475 4050 m
+gs 1 -1 sc (0) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+3375 4050 m
+gs 1 -1 sc (2) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+3825 4050 m
+gs 1 -1 sc (3) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+4320 4050 m
+gs 1 -1 sc (4) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+2925 4050 m
+gs 1 -1 sc (1) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+2970 4320 m
+gs 1 -1 sc (local indices) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+2475 4635 m
+gs 1 -1 sc (local array in processor 0) col0 sh gr
+% Polyline
+n 3150 1215 m 6750 1215 l 6750 1890 l 3150 1890 l cp gs col0 s gr
+% Polyline
+n 4950 1215 m 4950 1890 l gs col0 s gr
+% Polyline
+n 4050 1215 m 4050 1890 l gs col0 s gr
+% Polyline
+n 3600 1215 m 3600 1890 l gs col0 s gr
+% Polyline
+n 4500 1215 m 4500 1890 l gs col0 s gr
+% Polyline
+n 5850 1215 m 5850 1890 l gs col0 s gr
+% Polyline
+n 5400 1215 m 5400 1890 l gs col0 s gr
+% Polyline
+n 6300 1215 m 6300 1890 l gs col0 s gr
+% Polyline
+n 2520 3105 m 3375 1890 l gs col0 s gr
+% Polyline
+n 2970 3105 m 4230 1890 l gs col0 s gr
+% Polyline
+n 3375 3105 m 6030 1890 l gs col0 s gr
+% Polyline
+n 3825 3105 m 4725 1890 l gs col0 s gr
+% Polyline
+n 5490 3105 m 3465 1890 l gs col0 s gr
+% Polyline
+n 5850 3105 m 3870 1890 l gs col0 s gr
+% Polyline
+n 6345 3105 m 6525 1890 l gs col0 s gr
+% Polyline
+n 6795 3105 m 5625 1890 l gs col0 s gr
+% Polyline
+n 7290 3105 m 5175 1890 l gs col0 s gr
+% Polyline
+n 4320 3105 m 5535 1890 l gs col0 s gr
+/Times-Roman ff 180.00 scf sf
+3285 1035 m
+gs 1 -1 sc (0) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+3735 1035 m
+gs 1 -1 sc (1) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+4230 1035 m
+gs 1 -1 sc (2) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+4680 1035 m
+gs 1 -1 sc (3) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+5085 1035 m
+gs 1 -1 sc (4) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+5535 1035 m
+gs 1 -1 sc (5) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+5985 1035 m
+gs 1 -1 sc (6) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+6435 1035 m
+gs 1 -1 sc (7) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+5940 4320 m
+gs 1 -1 sc (local indices) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+5490 4635 m
+gs 1 -1 sc (local array in processor 1) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+3825 720 m
+gs 1 -1 sc (global array with global indices) col0 sh gr
+/Times-Italic ff 180.00 scf sf
+2880 1665 m
+gs 1 -1 sc (a:) col0 sh gr
+/Times-Italic ff 180.00 scf sf
+2070 3555 m
+gs 1 -1 sc (a0:) col0 sh gr
+/Times-Italic ff 180.00 scf sf
+4995 3555 m
+gs 1 -1 sc (a1:) col0 sh gr
+$F2psEnd
+rs
--- /dev/null
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: inkscape 0.44.1
+%%Pages: 1
+%%Orientation: Portrait
+%%BoundingBox: -43 616 613 832
+%%HiResBoundingBox: -43.106274 616.19711 612.40005 831.58167
+%%DocumentMedia: plain 596 842 0 () ()
+%%EndComments
+%%Page: 1 1
+0 842 translate
+0.8 -0.8 scale
+gsave [1 0 0 1 0 0] concat
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+130.75 35.229931 moveto
+168.75 35.229931 lineto
+168.75 70.229931 lineto
+130.75 70.229931 lineto
+130.75 35.229931 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+170.25 35.229931 moveto
+208.25 35.229931 lineto
+208.25 70.229931 lineto
+170.25 70.229931 lineto
+170.25 35.229931 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+565.25 35.229931 moveto
+603.25 35.229931 lineto
+603.25 70.229931 lineto
+565.25 70.229931 lineto
+565.25 35.229931 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+525.75 35.229931 moveto
+563.75 35.229931 lineto
+563.75 70.229931 lineto
+525.75 70.229931 lineto
+525.75 35.229931 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+486.25 35.229931 moveto
+524.25 35.229931 lineto
+524.25 70.229931 lineto
+486.25 70.229931 lineto
+486.25 35.229931 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+446.75 35.229931 moveto
+484.75 35.229931 lineto
+484.75 70.229931 lineto
+446.75 70.229931 lineto
+446.75 35.229931 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+407.25 35.229931 moveto
+445.25 35.229931 lineto
+445.25 70.229931 lineto
+407.25 70.229931 lineto
+407.25 35.229931 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+367.75 35.229931 moveto
+405.75 35.229931 lineto
+405.75 70.229931 lineto
+367.75 70.229931 lineto
+367.75 35.229931 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+328.25 35.229931 moveto
+366.25 35.229931 lineto
+366.25 70.229931 lineto
+328.25 70.229931 lineto
+328.25 35.229931 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+288.75 35.229931 moveto
+326.75 35.229931 lineto
+326.75 70.229931 lineto
+288.75 70.229931 lineto
+288.75 35.229931 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+249.25 35.229931 moveto
+287.25 35.229931 lineto
+287.25 70.229931 lineto
+249.25 70.229931 lineto
+249.25 35.229931 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+209.75 35.229931 moveto
+247.75 35.229931 lineto
+247.75 70.229931 lineto
+209.75 70.229931 lineto
+209.75 35.229931 lineto
+closepath
+stroke
+gsave [1 0 0 1 90.45711 -21.76955] concat
+gsave [1 0 0 -1 56 78.362183] concat
+gsave
+/newlatin1font {findfont dup length dict copy dup /Encoding ISOLatin1Encoding put definefont} def
+/(BitstreamVeraSans-Roman-ISOLatin1) /(BitstreamVeraSans-Roman) newlatin1font
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(0) show
+grestore
+grestore
+gsave [1 0 0 -1 95.71582 78.369019] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(1) show
+grestore
+grestore
+gsave [1 0 0 -1 135.17871 78.461304] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(2) show
+grestore
+grestore
+gsave [1 0 0 -1 174.25195 78.362183] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(3) show
+grestore
+grestore
+gsave [1 0 0 -1 213.27051 78.369019] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(4) show
+grestore
+grestore
+gsave [1 0 0 -1 253.06152 78.269897] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(5) show
+grestore
+grestore
+gsave [1 0 0 -1 292.07324 78.362183] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(6) show
+grestore
+grestore
+gsave [1 0 0 -1 331.74121 78.369019] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(7) show
+grestore
+grestore
+gsave [1 0 0 -1 370.85547 78.362183] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(8) show
+grestore
+grestore
+gsave [1 0 0 -1 410.23633 78.362183] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(9) show
+grestore
+grestore
+gsave [1 0 0 -1 440.62109 78.362183] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(10) show
+grestore
+grestore
+gsave [1 0 0 -1 480.33691 78.369019] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(11) show
+grestore
+grestore
+grestore
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+644.59235 134.57874 moveto
+682.59235 134.57874 lineto
+682.59235 169.57874 lineto
+644.59235 169.57874 lineto
+644.59235 134.57874 lineto
+closepath
+stroke
+gsave [1 0 0 -1 320.31937 23.521814] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(global array) show
+grestore
+grestore
+gsave [1 0 0 -1 94.752312 53.220303] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(a:) show
+grestore
+grestore
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+54.781971 134.38783 moveto
+92.781971 134.38783 lineto
+92.781971 169.38783 lineto
+54.781971 169.38783 lineto
+54.781971 134.38783 lineto
+closepath
+stroke
+gsave
+0.79607844 0.79607844 0.79607844 setrgbcolor
+newpath
+291.03198 133.63783 moveto
+330.53198 133.63783 lineto
+330.53198 170.13783 lineto
+291.03198 170.13783 lineto
+291.03198 133.63783 lineto
+closepath
+fill
+grestore
+0 0 0 setrgbcolor
+[] 0 setdash
+1 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+291.03198 133.63783 moveto
+330.53198 133.63783 lineto
+330.53198 170.13783 lineto
+291.03198 170.13783 lineto
+291.03198 133.63783 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+252.28197 134.38783 moveto
+290.28197 134.38783 lineto
+290.28197 169.38783 lineto
+252.28197 169.38783 lineto
+252.28197 134.38783 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+212.78197 134.38783 moveto
+250.78197 134.38783 lineto
+250.78197 169.38783 lineto
+212.78197 169.38783 lineto
+212.78197 134.38783 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+173.28197 134.38783 moveto
+211.28197 134.38783 lineto
+211.28197 169.38783 lineto
+173.28197 169.38783 lineto
+173.28197 134.38783 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+133.78197 134.38783 moveto
+171.78197 134.38783 lineto
+171.78197 169.38783 lineto
+133.78197 169.38783 lineto
+133.78197 134.38783 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+94.281967 134.38783 moveto
+132.28197 134.38783 lineto
+132.28197 169.38783 lineto
+94.281967 169.38783 lineto
+94.281967 134.38783 lineto
+closepath
+stroke
+gsave [1.05799 0 0 1 -76.67982 40.7414] concat
+gsave [1 0 0 -1 138.59293 118.27412] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(0) show
+grestore
+grestore
+gsave [1 0 0 -1 176.39273 118.28096] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(1) show
+grestore
+grestore
+gsave [1 0 0 -1 213.93961 118.37325] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(2) show
+grestore
+grestore
+gsave [1 0 0 -1 251.09683 118.27412] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(3) show
+grestore
+grestore
+gsave [1 0 0 -1 288.19937 118.28096] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(4) show
+grestore
+grestore
+gsave [1 0 0 -1 326.07437 118.18184] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(5) show
+grestore
+grestore
+gsave [1 0 0 -1 363.17007 118.27412] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(6) show
+grestore
+grestore
+grestore
+gsave
+0.79607844 0.79607844 0.79607844 setrgbcolor
+newpath
+408.72391 134.59494 moveto
+446.72391 134.59494 lineto
+446.72391 169.59494 lineto
+408.72391 169.59494 lineto
+408.72391 134.59494 lineto
+closepath
+fill
+grestore
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+408.72391 134.59494 moveto
+446.72391 134.59494 lineto
+446.72391 169.59494 lineto
+408.72391 169.59494 lineto
+408.72391 134.59494 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+606.22388 134.59494 moveto
+644.22388 134.59494 lineto
+644.22388 169.59494 lineto
+606.22388 169.59494 lineto
+606.22388 134.59494 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+566.72388 134.59494 moveto
+604.72388 134.59494 lineto
+604.72388 169.59494 lineto
+566.72388 169.59494 lineto
+566.72388 134.59494 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+527.22388 134.59494 moveto
+565.22388 134.59494 lineto
+565.22388 169.59494 lineto
+527.22388 169.59494 lineto
+527.22388 134.59494 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+487.72391 134.59494 moveto
+525.72391 134.59494 lineto
+525.72391 169.59494 lineto
+487.72391 169.59494 lineto
+487.72391 134.59494 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+448.22391 134.59494 moveto
+486.22391 134.59494 lineto
+486.22391 169.59494 lineto
+448.22391 169.59494 lineto
+448.22391 134.59494 lineto
+closepath
+stroke
+gsave [1 0 0 -1 421.10342 157.16211] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(5) show
+grestore
+grestore
+gsave [1 0 0 -1 461.11514 157.25439] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(6) show
+grestore
+grestore
+gsave [1 0 0 -1 501.78314 157.26123] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(7) show
+grestore
+grestore
+gsave [1 0 0 -1 541.8974 157.25439] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(8) show
+grestore
+grestore
+gsave [1 0 0 -1 582.27826 157.25439] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(9) show
+grestore
+grestore
+gsave [1 0 0 -1 613.66302 157.25439] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(10) show
+grestore
+grestore
+gsave [1 0 0 -1 654.37885 157.26123] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(11) show
+grestore
+grestore
+gsave
+0.79607844 0.79607844 0.79607844 setrgbcolor
+newpath
+292.38773 195.09746 moveto
+330.38773 195.09746 lineto
+330.38773 230.09746 lineto
+292.38773 230.09746 lineto
+292.38773 195.09746 lineto
+closepath
+fill
+grestore
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+292.38773 195.09746 moveto
+330.38773 195.09746 lineto
+330.38773 230.09746 lineto
+292.38773 230.09746 lineto
+292.38773 195.09746 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+252.88774 195.09746 moveto
+290.88774 195.09746 lineto
+290.88774 230.09746 lineto
+252.88774 230.09746 lineto
+252.88774 195.09746 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+213.38774 195.09746 moveto
+251.38774 195.09746 lineto
+251.38774 230.09746 lineto
+213.38774 230.09746 lineto
+213.38774 195.09746 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+173.88776 195.09746 moveto
+211.88776 195.09746 lineto
+211.88776 230.09746 lineto
+173.88776 230.09746 lineto
+173.88776 195.09746 lineto
+closepath
+stroke
+gsave
+0.79607844 0.79607844 0.79607844 setrgbcolor
+newpath
+134.38776 195.09746 moveto
+172.38776 195.09746 lineto
+172.38776 230.09746 lineto
+134.38776 230.09746 lineto
+134.38776 195.09746 lineto
+closepath
+fill
+grestore
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+134.38776 195.09746 moveto
+172.38776 195.09746 lineto
+172.38776 230.09746 lineto
+134.38776 230.09746 lineto
+134.38776 195.09746 lineto
+closepath
+stroke
+gsave
+0.79607844 0.79607844 0.79607844 setrgbcolor
+newpath
+94.887749 195.09746 moveto
+132.88775 195.09746 lineto
+132.88775 230.09746 lineto
+94.887749 230.09746 lineto
+94.887749 195.09746 lineto
+closepath
+fill
+grestore
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+94.887749 195.09746 moveto
+132.88775 195.09746 lineto
+132.88775 230.09746 lineto
+94.887749 230.09746 lineto
+94.887749 195.09746 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+55.387745 195.09746 moveto
+93.387745 195.09746 lineto
+93.387745 230.09746 lineto
+55.387745 230.09746 lineto
+55.387745 195.09746 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+15.887744 195.09746 moveto
+53.887744 195.09746 lineto
+53.887744 230.09746 lineto
+15.887744 230.09746 lineto
+15.887744 195.09746 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+-23.612255 195.09746 moveto
+14.387745 195.09746 lineto
+14.387745 230.09746 lineto
+-23.612255 230.09746 lineto
+-23.612255 195.09746 lineto
+closepath
+stroke
+gsave [1.065237 0 0 1 -54.35452 -47.7132] concat
+gsave [1 0 0 -1 41.012192 264.64523] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(0) show
+grestore
+grestore
+gsave [1 0 0 -1 78.429184 264.65207] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(1) show
+grestore
+grestore
+gsave [1 0 0 -1 115.59325 264.74435] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(2) show
+grestore
+grestore
+gsave [1 0 0 -1 152.36766 264.64523] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(3) show
+grestore
+grestore
+gsave [1 0 0 -1 189.52489 264.55295] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(5) show
+grestore
+grestore
+gsave [1 0 0 -1 226.23778 264.64523] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(6) show
+grestore
+grestore
+gsave [1 0 0 -1 263.60693 264.65207] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(7) show
+grestore
+grestore
+gsave [1 0 0 -1 300.42236 264.64523] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(8) show
+grestore
+grestore
+gsave [1 0 0 -1 337.50439 264.64523] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(9) show
+grestore
+grestore
+grestore
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+726.75006 191.62869 moveto
+764.75006 191.62869 lineto
+764.75006 226.62869 lineto
+726.75006 226.62869 lineto
+726.75006 191.62869 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+687.25006 191.62869 moveto
+725.25006 191.62869 lineto
+725.25006 226.62869 lineto
+687.25006 226.62869 lineto
+687.25006 191.62869 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+647.75006 191.62869 moveto
+685.75006 191.62869 lineto
+685.75006 226.62869 lineto
+647.75006 226.62869 lineto
+647.75006 191.62869 lineto
+closepath
+stroke
+gsave
+0.79607844 0.79607844 0.79607844 setrgbcolor
+newpath
+608.25006 191.62869 moveto
+646.25006 191.62869 lineto
+646.25006 226.62869 lineto
+608.25006 226.62869 lineto
+608.25006 191.62869 lineto
+closepath
+fill
+grestore
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+608.25006 191.62869 moveto
+646.25006 191.62869 lineto
+646.25006 226.62869 lineto
+608.25006 226.62869 lineto
+608.25006 191.62869 lineto
+closepath
+stroke
+gsave
+0.79607844 0.79607844 0.79607844 setrgbcolor
+newpath
+568.75006 191.62869 moveto
+606.75006 191.62869 lineto
+606.75006 226.62869 lineto
+568.75006 226.62869 lineto
+568.75006 191.62869 lineto
+closepath
+fill
+grestore
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+568.75006 191.62869 moveto
+606.75006 191.62869 lineto
+606.75006 226.62869 lineto
+568.75006 226.62869 lineto
+568.75006 191.62869 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+529.25006 191.62869 moveto
+567.25006 191.62869 lineto
+567.25006 226.62869 lineto
+529.25006 226.62869 lineto
+529.25006 191.62869 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+489.75006 191.62869 moveto
+527.75006 191.62869 lineto
+527.75006 226.62869 lineto
+489.75006 226.62869 lineto
+489.75006 191.62869 lineto
+closepath
+stroke
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+450.25006 191.62869 moveto
+488.25006 191.62869 lineto
+488.25006 226.62869 lineto
+450.25006 226.62869 lineto
+450.25006 191.62869 lineto
+closepath
+stroke
+gsave
+0.79607844 0.79607844 0.79607844 setrgbcolor
+newpath
+410.75006 191.62869 moveto
+448.75006 191.62869 lineto
+448.75006 226.62869 lineto
+410.75006 226.62869 lineto
+410.75006 191.62869 lineto
+closepath
+fill
+grestore
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+410.75006 191.62869 moveto
+448.75006 191.62869 lineto
+448.75006 226.62869 lineto
+410.75006 226.62869 lineto
+410.75006 191.62869 lineto
+closepath
+stroke
+gsave [1 0 0 1 244.4658 -120.5452] concat
+gsave [1 0 0 -1 181.01933 335.45502] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(2) show
+grestore
+grestore
+gsave [1 0 0 -1 221.09258 335.3559] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(3) show
+grestore
+grestore
+gsave [1 0 0 -1 261.11115 335.36273] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(4) show
+grestore
+grestore
+gsave [1 0 0 -1 301.90216 335.26361] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(5) show
+grestore
+grestore
+gsave [1 0 0 -1 341.91388 335.3559] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(6) show
+grestore
+grestore
+gsave [1 0 0 -1 382.34259 335.3559] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(8) show
+grestore
+grestore
+gsave [1 0 0 -1 422.72345 335.3559] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(9) show
+grestore
+grestore
+gsave [1 0 0 -1 454.10822 335.3559] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(10) show
+grestore
+grestore
+gsave [1 0 0 -1 494.82404 335.36273] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(11) show
+grestore
+grestore
+grestore
+gsave [1 0 0 -1 22.627417 158.24216] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(a0:) show
+grestore
+grestore
+gsave [1 0 0 -1 381.13055 161.07059] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(a1:) show
+grestore
+grestore
+gsave [1 0 0 -1 -55.154327 213.39648] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(b0:) show
+grestore
+grestore
+gsave [1 0 0 -1 381.83765 211.98228] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(b1:) show
+grestore
+grestore
+gsave [1.03432 0 0 0.966819 0 0] concat
+gsave [1 0 0 -1 317.21094 112.36991] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+13.535465 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(local views) show
+grestore
+grestore
+grestore
+0 0 0 setrgbcolor
+[] 0 setdash
+1 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+370 281.61579 moveto
+370 126.86218 lineto
+stroke
+gsave [1 0 0 -1 143.62598 255.36218] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(P0) show
+grestore
+grestore
+gsave [1 0 0 -1 578.62598 253.86218] concat
+gsave
+/(BitstreamVeraSans-Roman-ISOLatin1) findfont
+14 scalefont
+setfont
+0 0 0 setrgbcolor
+newpath
+0 0 moveto
+(P1) show
+grestore
+grestore
+grestore
+showpage
+%%EOF
--- /dev/null
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: inkscape 0.44.1
+%%Pages: 1
+%%Orientation: Portrait
+%%BoundingBox: -5 414 276 601
+%%HiResBoundingBox: -5.9999911 414 276 600.4
+%%DocumentMedia: plain 596 842 0 () ()
+%%EndComments
+%%Page: 1 1
+0 842 translate
+0.8 -0.8 scale
+gsave [1 0 0 1 0 0] concat
+gsave
+0 0 0 setrgbcolor
+newpath
+11.34082 347.36218 moveto
+10.730139 348.41037 10.276689 349.44715 9.9804688 350.47253 curveto
+9.6842421 351.49793 9.5361303 352.53699 9.5361328 353.58972 curveto
+9.5361303 354.64246 9.6842421 355.68608 9.9804688 356.72058 curveto
+10.281247 357.75053 10.734697 358.78731 11.34082 359.83093 curveto
+10.24707 359.83093 lineto
+9.563474 358.75997 9.0507792 357.70723 8.7089844 356.67273 curveto
+8.3717434 355.63823 8.2031238 354.61056 8.203125 353.58972 curveto
+8.2031238 352.57345 8.3717434 351.55034 8.7089844 350.52039 curveto
+9.0462219 349.49045 9.5589167 348.43771 10.24707 347.36218 curveto
+11.34082 347.36218 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+15.155273 356.82312 moveto
+19.974609 356.82312 lineto
+19.974609 357.98523 lineto
+13.494141 357.98523 lineto
+13.494141 356.82312 lineto
+14.018228 356.2808 14.731443 355.55392 15.633789 354.64246 curveto
+16.540686 353.72644 17.110347 353.13628 17.342773 352.87195 curveto
+17.784825 352.37521 18.092442 351.95594 18.265625 351.61414 curveto
+18.443353 351.26779 18.53222 350.92827 18.532227 350.59558 curveto
+18.53222 350.05327 18.340814 349.61121 17.958008 349.26941 curveto
+17.579747 348.92762 17.085282 348.75672 16.474609 348.75671 curveto
+16.041663 348.75672 15.583656 348.83192 15.100586 348.9823 curveto
+14.622068 349.1327 14.109373 349.36056 13.5625 349.66589 curveto
+13.5625 348.27136 lineto
+14.118488 348.04806 14.638019 347.87945 15.121094 347.7655 curveto
+15.604164 347.65158 16.04622 347.59461 16.447266 347.5946 curveto
+17.504552 347.59461 18.34765 347.85894 18.976562 348.38757 curveto
+19.605462 348.91623 19.919914 349.62261 19.919922 350.50671 curveto
+19.919914 350.92599 19.840162 351.32475 19.680664 351.703 curveto
+19.525709 352.07671 19.240879 352.51876 18.826172 353.02917 curveto
+18.712233 353.16134 18.349929 353.54415 17.739258 354.17761 curveto
+17.128576 354.80652 16.267249 355.68836 15.155273 356.82312 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+23.023438 356.2489 moveto
+24.46582 356.2489 lineto
+24.46582 357.42468 lineto
+23.344727 359.61218 lineto
+22.462891 359.61218 lineto
+23.023438 357.42468 lineto
+23.023438 356.2489 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+28.526367 356.82312 moveto
+33.345703 356.82312 lineto
+33.345703 357.98523 lineto
+26.865234 357.98523 lineto
+26.865234 356.82312 lineto
+27.389321 356.2808 28.102537 355.55392 29.004883 354.64246 curveto
+29.91178 353.72644 30.481441 353.13628 30.713867 352.87195 curveto
+31.155919 352.37521 31.463536 351.95594 31.636719 351.61414 curveto
+31.814447 351.26779 31.903314 350.92827 31.90332 350.59558 curveto
+31.903314 350.05327 31.711908 349.61121 31.329102 349.26941 curveto
+30.950841 348.92762 30.456376 348.75672 29.845703 348.75671 curveto
+29.412757 348.75672 28.954749 348.83192 28.47168 348.9823 curveto
+27.993162 349.1327 27.480467 349.36056 26.933594 349.66589 curveto
+26.933594 348.27136 lineto
+27.489582 348.04806 28.009112 347.87945 28.492188 347.7655 curveto
+28.975257 347.65158 29.417314 347.59461 29.818359 347.5946 curveto
+30.875646 347.59461 31.718744 347.85894 32.347656 348.38757 curveto
+32.976555 348.91623 33.291008 349.62261 33.291016 350.50671 curveto
+33.291008 350.92599 33.211256 351.32475 33.051758 351.703 curveto
+32.896803 352.07671 32.611972 352.51876 32.197266 353.02917 curveto
+32.083327 353.16134 31.721023 353.54415 31.110352 354.17761 curveto
+30.49967 354.80652 29.638343 355.68836 28.526367 356.82312 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+36.394531 356.2489 moveto
+37.836914 356.2489 lineto
+37.836914 357.42468 lineto
+36.71582 359.61218 lineto
+35.833984 359.61218 lineto
+36.394531 357.42468 lineto
+36.394531 356.2489 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+43.49707 351.21082 moveto
+42.822588 351.21082 42.289385 351.47514 41.897461 352.00378 curveto
+41.505532 352.52788 41.309568 353.24793 41.30957 354.16394 curveto
+41.309568 355.07996 41.503253 355.80229 41.890625 356.33093 curveto
+42.282549 356.85502 42.81803 357.11707 43.49707 357.11707 curveto
+44.166987 357.11707 44.697911 356.85274 45.089844 356.3241 curveto
+45.481765 355.79545 45.677728 355.0754 45.677734 354.16394 curveto
+45.677728 353.25704 45.481765 352.53927 45.089844 352.01062 curveto
+44.697911 351.47742 44.166987 351.21082 43.49707 351.21082 curveto
+43.49707 350.14441 moveto
+44.590815 350.14442 45.449864 350.49989 46.074219 351.21082 curveto
+46.69856 351.92176 47.010734 352.90613 47.010742 354.16394 curveto
+47.010734 355.4172 46.69856 356.40157 46.074219 357.11707 curveto
+45.449864 357.828 44.590815 358.18347 43.49707 358.18347 curveto
+42.39876 358.18347 41.537433 357.828 40.913086 357.11707 curveto
+40.293293 356.40157 39.983398 355.4172 39.983398 354.16394 curveto
+39.983398 352.90613 40.293293 351.92176 40.913086 351.21082 curveto
+41.537433 350.49989 42.39876 350.14442 43.49707 350.14441 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+48.890625 347.36218 moveto
+49.984375 347.36218 lineto
+50.667966 348.43771 51.178382 349.49045 51.515625 350.52039 curveto
+51.857418 351.55034 52.028316 352.57345 52.02832 353.58972 curveto
+52.028316 354.61056 51.857418 355.63823 51.515625 356.67273 curveto
+51.178382 357.70723 50.667966 358.75997 49.984375 359.83093 curveto
+48.890625 359.83093 lineto
+49.496743 358.78731 49.947914 357.75053 50.244141 356.72058 curveto
+50.544919 355.68608 50.69531 354.64246 50.695312 353.58972 curveto
+50.69531 352.53699 50.544919 351.49793 50.244141 350.47253 curveto
+49.947914 349.44715 49.496743 348.41037 48.890625 347.36218 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+32.34082 327.36218 moveto
+31.730139 328.41037 31.276689 329.44715 30.980469 330.47253 curveto
+30.684242 331.49793 30.53613 332.53699 30.536133 333.58972 curveto
+30.53613 334.64246 30.684242 335.68608 30.980469 336.72058 curveto
+31.281247 337.75053 31.734697 338.78731 32.34082 339.83093 curveto
+31.24707 339.83093 lineto
+30.563474 338.75997 30.050779 337.70723 29.708984 336.67273 curveto
+29.371743 335.63823 29.203124 334.61056 29.203125 333.58972 curveto
+29.203124 332.57345 29.371743 331.55034 29.708984 330.52039 curveto
+30.046222 329.49045 30.558917 328.43771 31.24707 327.36218 curveto
+32.34082 327.36218 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+37.918945 328.68835 moveto
+37.208004 328.68836 36.672523 329.03927 36.3125 329.74109 curveto
+35.957029 330.43836 35.779295 331.48882 35.779297 332.89246 curveto
+35.779295 334.29155 35.957029 335.342 36.3125 336.04382 curveto
+36.672523 336.74109 37.208004 337.08972 37.918945 337.08972 curveto
+38.634435 337.08972 39.169916 336.74109 39.525391 336.04382 curveto
+39.88541 335.342 40.065423 334.29155 40.06543 332.89246 curveto
+40.065423 331.48882 39.88541 330.43836 39.525391 329.74109 curveto
+39.169916 329.03927 38.634435 328.68836 37.918945 328.68835 curveto
+37.918945 327.5946 moveto
+39.06282 327.59461 39.93554 328.04806 40.537109 328.95496 curveto
+41.143221 329.85731 41.446281 331.16981 41.446289 332.89246 curveto
+41.446281 334.61056 41.143221 335.92306 40.537109 336.82996 curveto
+39.93554 337.7323 39.06282 338.18347 37.918945 338.18347 curveto
+36.775062 338.18347 35.900063 337.7323 35.293945 336.82996 curveto
+34.692382 335.92306 34.391601 334.61056 34.391602 332.89246 curveto
+34.391601 331.16981 34.692382 329.85731 35.293945 328.95496 curveto
+35.900063 328.04806 36.775062 327.59461 37.918945 327.5946 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+44.023438 336.2489 moveto
+45.46582 336.2489 lineto
+45.46582 337.42468 lineto
+44.344727 339.61218 lineto
+43.462891 339.61218 lineto
+44.023438 337.42468 lineto
+44.023438 336.2489 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+51.290039 328.68835 moveto
+50.579098 328.68836 50.043617 329.03927 49.683594 329.74109 curveto
+49.328123 330.43836 49.150388 331.48882 49.150391 332.89246 curveto
+49.150388 334.29155 49.328123 335.342 49.683594 336.04382 curveto
+50.043617 336.74109 50.579098 337.08972 51.290039 337.08972 curveto
+52.005529 337.08972 52.54101 336.74109 52.896484 336.04382 curveto
+53.256504 335.342 53.436517 334.29155 53.436523 332.89246 curveto
+53.436517 331.48882 53.256504 330.43836 52.896484 329.74109 curveto
+52.54101 329.03927 52.005529 328.68836 51.290039 328.68835 curveto
+51.290039 327.5946 moveto
+52.433914 327.59461 53.306634 328.04806 53.908203 328.95496 curveto
+54.514315 329.85731 54.817375 331.16981 54.817383 332.89246 curveto
+54.817375 334.61056 54.514315 335.92306 53.908203 336.82996 curveto
+53.306634 337.7323 52.433914 338.18347 51.290039 338.18347 curveto
+50.146156 338.18347 49.271156 337.7323 48.665039 336.82996 curveto
+48.063475 335.92306 47.762694 334.61056 47.762695 332.89246 curveto
+47.762694 331.16981 48.063475 329.85731 48.665039 328.95496 curveto
+49.271156 328.04806 50.146156 327.59461 51.290039 327.5946 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+57.394531 336.2489 moveto
+58.836914 336.2489 lineto
+58.836914 337.42468 lineto
+57.71582 339.61218 lineto
+56.833984 339.61218 lineto
+57.394531 337.42468 lineto
+57.394531 336.2489 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+64.49707 331.21082 moveto
+63.822588 331.21082 63.289385 331.47514 62.897461 332.00378 curveto
+62.505532 332.52788 62.309568 333.24793 62.30957 334.16394 curveto
+62.309568 335.07996 62.503253 335.80229 62.890625 336.33093 curveto
+63.282549 336.85502 63.81803 337.11707 64.49707 337.11707 curveto
+65.166987 337.11707 65.697911 336.85274 66.089844 336.3241 curveto
+66.481765 335.79545 66.677728 335.0754 66.677734 334.16394 curveto
+66.677728 333.25704 66.481765 332.53927 66.089844 332.01062 curveto
+65.697911 331.47742 65.166987 331.21082 64.49707 331.21082 curveto
+64.49707 330.14441 moveto
+65.590815 330.14442 66.449864 330.49989 67.074219 331.21082 curveto
+67.69856 331.92176 68.010734 332.90613 68.010742 334.16394 curveto
+68.010734 335.4172 67.69856 336.40157 67.074219 337.11707 curveto
+66.449864 337.828 65.590815 338.18347 64.49707 338.18347 curveto
+63.39876 338.18347 62.537433 337.828 61.913086 337.11707 curveto
+61.293293 336.40157 60.983398 335.4172 60.983398 334.16394 curveto
+60.983398 332.90613 61.293293 331.92176 61.913086 331.21082 curveto
+62.537433 330.49989 63.39876 330.14442 64.49707 330.14441 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+69.890625 327.36218 moveto
+70.984375 327.36218 lineto
+71.667966 328.43771 72.178382 329.49045 72.515625 330.52039 curveto
+72.857418 331.55034 73.028316 332.57345 73.02832 333.58972 curveto
+73.028316 334.61056 72.857418 335.63823 72.515625 336.67273 curveto
+72.178382 337.70723 71.667966 338.75997 70.984375 339.83093 curveto
+69.890625 339.83093 lineto
+70.496743 338.78731 70.947914 337.75053 71.244141 336.72058 curveto
+71.544919 335.68608 71.69531 334.64246 71.695312 333.58972 curveto
+71.69531 332.53699 71.544919 331.49793 71.244141 330.47253 curveto
+70.947914 329.44715 70.496743 328.41037 69.890625 327.36218 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+77.683594 328.36218 moveto
+77.072913 329.41037 76.619463 330.44715 76.323242 331.47253 curveto
+76.027016 332.49793 75.878904 333.53699 75.878906 334.58972 curveto
+75.878904 335.64246 76.027016 336.68608 76.323242 337.72058 curveto
+76.62402 338.75053 77.07747 339.78731 77.683594 340.83093 curveto
+76.589844 340.83093 lineto
+75.906247 339.75997 75.393553 338.70723 75.051758 337.67273 curveto
+74.714517 336.63823 74.545897 335.61056 74.545898 334.58972 curveto
+74.545897 333.57345 74.714517 332.55034 75.051758 331.52039 curveto
+75.388995 330.49045 75.90169 329.43771 76.589844 328.36218 curveto
+77.683594 328.36218 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+80.547852 337.82312 moveto
+82.803711 337.82312 lineto
+82.803711 330.03699 lineto
+80.349609 330.52917 lineto
+80.349609 329.27136 lineto
+82.790039 328.77917 lineto
+84.170898 328.77917 lineto
+84.170898 337.82312 lineto
+86.426758 337.82312 lineto
+86.426758 338.98523 lineto
+80.547852 338.98523 lineto
+80.547852 337.82312 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+89.366211 337.2489 moveto
+90.808594 337.2489 lineto
+90.808594 338.42468 lineto
+89.6875 340.61218 lineto
+88.805664 340.61218 lineto
+89.366211 338.42468 lineto
+89.366211 337.2489 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+93.918945 337.82312 moveto
+96.174805 337.82312 lineto
+96.174805 330.03699 lineto
+93.720703 330.52917 lineto
+93.720703 329.27136 lineto
+96.161133 328.77917 lineto
+97.541992 328.77917 lineto
+97.541992 337.82312 lineto
+99.797852 337.82312 lineto
+99.797852 338.98523 lineto
+93.918945 338.98523 lineto
+93.918945 337.82312 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+102.7373 337.2489 moveto
+104.17969 337.2489 lineto
+104.17969 338.42468 lineto
+103.05859 340.61218 lineto
+102.17676 340.61218 lineto
+102.7373 338.42468 lineto
+102.7373 337.2489 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+109.83984 332.21082 moveto
+109.16536 332.21082 108.63216 332.47514 108.24023 333.00378 curveto
+107.8483 333.52788 107.65234 334.24793 107.65234 335.16394 curveto
+107.65234 336.07996 107.84603 336.80229 108.2334 337.33093 curveto
+108.62532 337.85502 109.1608 338.11707 109.83984 338.11707 curveto
+110.50976 338.11707 111.04068 337.85274 111.43262 337.3241 curveto
+111.82454 336.79545 112.0205 336.0754 112.02051 335.16394 curveto
+112.0205 334.25704 111.82454 333.53927 111.43262 333.01062 curveto
+111.04068 332.47742 110.50976 332.21082 109.83984 332.21082 curveto
+109.83984 331.14441 moveto
+110.93359 331.14442 111.79264 331.49989 112.41699 332.21082 curveto
+113.04133 332.92176 113.35351 333.90613 113.35352 335.16394 curveto
+113.35351 336.4172 113.04133 337.40157 112.41699 338.11707 curveto
+111.79264 338.828 110.93359 339.18347 109.83984 339.18347 curveto
+108.74153 339.18347 107.88021 338.828 107.25586 338.11707 curveto
+106.63607 337.40157 106.32617 336.4172 106.32617 335.16394 curveto
+106.32617 333.90613 106.63607 332.92176 107.25586 332.21082 curveto
+107.88021 331.49989 108.74153 331.14442 109.83984 331.14441 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+115.2334 328.36218 moveto
+116.32715 328.36218 lineto
+117.01074 329.43771 117.52116 330.49045 117.8584 331.52039 curveto
+118.20019 332.55034 118.37109 333.57345 118.37109 334.58972 curveto
+118.37109 335.61056 118.20019 336.63823 117.8584 337.67273 curveto
+117.52116 338.70723 117.01074 339.75997 116.32715 340.83093 curveto
+115.2334 340.83093 lineto
+115.83952 339.78731 116.29069 338.75053 116.58691 337.72058 curveto
+116.88769 336.68608 117.03808 335.64246 117.03809 334.58972 curveto
+117.03808 333.53699 116.88769 332.49793 116.58691 331.47253 curveto
+116.29069 330.44715 115.83952 329.41037 115.2334 328.36218 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+56.84082 347.36218 moveto
+56.230139 348.41037 55.776689 349.44715 55.480469 350.47253 curveto
+55.184242 351.49793 55.03613 352.53699 55.036133 353.58972 curveto
+55.03613 354.64246 55.184242 355.68608 55.480469 356.72058 curveto
+55.781247 357.75053 56.234697 358.78731 56.84082 359.83093 curveto
+55.74707 359.83093 lineto
+55.063474 358.75997 54.550779 357.70723 54.208984 356.67273 curveto
+53.871743 355.63823 53.703124 354.61056 53.703125 353.58972 curveto
+53.703124 352.57345 53.871743 351.55034 54.208984 350.52039 curveto
+54.546222 349.49045 55.058917 348.43771 55.74707 347.36218 curveto
+56.84082 347.36218 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+63.649414 352.4823 moveto
+64.310215 352.62358 64.825188 352.91753 65.194336 353.36414 curveto
+65.568026 353.81075 65.754875 354.36219 65.754883 355.01843 curveto
+65.754875 356.0256 65.408521 356.80489 64.71582 357.35632 curveto
+64.023106 357.90776 63.038732 358.18347 61.762695 358.18347 curveto
+61.334307 358.18347 60.89225 358.14018 60.436523 358.05359 curveto
+59.98535 357.97156 59.518228 357.84623 59.035156 357.67761 curveto
+59.035156 356.3446 lineto
+59.417967 356.56791 59.837238 356.73653 60.292969 356.85046 curveto
+60.748695 356.9644 61.224932 357.02136 61.72168 357.02136 curveto
+62.58756 357.02136 63.246088 356.85047 63.697266 356.50867 curveto
+64.152989 356.16687 64.380853 355.67013 64.380859 355.01843 curveto
+64.380853 354.41687 64.168939 353.94747 63.745117 353.61023 curveto
+63.325841 353.26844 62.74023 353.09754 61.988281 353.09753 curveto
+60.798828 353.09753 lineto
+60.798828 351.96277 lineto
+62.042969 351.96277 lineto
+62.722 351.96277 63.241531 351.82833 63.601562 351.55945 curveto
+63.961583 351.28602 64.141595 350.89409 64.141602 350.38367 curveto
+64.141595 349.85959 63.954747 349.45855 63.581055 349.18054 curveto
+63.211909 348.898 62.680985 348.75672 61.988281 348.75671 curveto
+61.610022 348.75672 61.204424 348.79774 60.771484 348.87976 curveto
+60.338539 348.9618 59.862303 349.08941 59.342773 349.26257 curveto
+59.342773 348.0321 lineto
+59.86686 347.88628 60.356768 347.77691 60.8125 347.70398 curveto
+61.272783 347.63107 61.705725 347.59461 62.111328 347.5946 curveto
+63.1595 347.59461 63.988926 347.83387 64.599609 348.31238 curveto
+65.210279 348.78635 65.515617 349.42892 65.515625 350.24011 curveto
+65.515617 350.80522 65.353834 351.28374 65.030273 351.67566 curveto
+64.706699 352.06303 64.246413 352.33191 63.649414 352.4823 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+68.523438 356.2489 moveto
+69.96582 356.2489 lineto
+69.96582 357.42468 lineto
+68.844727 359.61218 lineto
+67.962891 359.61218 lineto
+68.523438 357.42468 lineto
+68.523438 356.2489 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+77.020508 352.4823 moveto
+77.681309 352.62358 78.196282 352.91753 78.56543 353.36414 curveto
+78.93912 353.81075 79.125969 354.36219 79.125977 355.01843 curveto
+79.125969 356.0256 78.779615 356.80489 78.086914 357.35632 curveto
+77.3942 357.90776 76.409826 358.18347 75.133789 358.18347 curveto
+74.7054 358.18347 74.263343 358.14018 73.807617 358.05359 curveto
+73.356443 357.97156 72.889321 357.84623 72.40625 357.67761 curveto
+72.40625 356.3446 lineto
+72.789061 356.56791 73.208331 356.73653 73.664062 356.85046 curveto
+74.119789 356.9644 74.596025 357.02136 75.092773 357.02136 curveto
+75.958654 357.02136 76.617182 356.85047 77.068359 356.50867 curveto
+77.524082 356.16687 77.751947 355.67013 77.751953 355.01843 curveto
+77.751947 354.41687 77.540033 353.94747 77.116211 353.61023 curveto
+76.696935 353.26844 76.111323 353.09754 75.359375 353.09753 curveto
+74.169922 353.09753 lineto
+74.169922 351.96277 lineto
+75.414062 351.96277 lineto
+76.093094 351.96277 76.612625 351.82833 76.972656 351.55945 curveto
+77.332676 351.28602 77.512689 350.89409 77.512695 350.38367 curveto
+77.512689 349.85959 77.32584 349.45855 76.952148 349.18054 curveto
+76.583003 348.898 76.052079 348.75672 75.359375 348.75671 curveto
+74.981116 348.75672 74.575518 348.79774 74.142578 348.87976 curveto
+73.709633 348.9618 73.233397 349.08941 72.713867 349.26257 curveto
+72.713867 348.0321 lineto
+73.237954 347.88628 73.727862 347.77691 74.183594 347.70398 curveto
+74.643877 347.63107 75.076819 347.59461 75.482422 347.5946 curveto
+76.530594 347.59461 77.36002 347.83387 77.970703 348.31238 curveto
+78.581373 348.78635 78.886711 349.42892 78.886719 350.24011 curveto
+78.886711 350.80522 78.724928 351.28374 78.401367 351.67566 curveto
+78.077793 352.06303 77.617507 352.33191 77.020508 352.4823 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+81.894531 356.2489 moveto
+83.336914 356.2489 lineto
+83.336914 357.42468 lineto
+82.21582 359.61218 lineto
+81.333984 359.61218 lineto
+81.894531 357.42468 lineto
+81.894531 356.2489 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+88.99707 351.21082 moveto
+88.322588 351.21082 87.789385 351.47514 87.397461 352.00378 curveto
+87.005532 352.52788 86.809568 353.24793 86.80957 354.16394 curveto
+86.809568 355.07996 87.003253 355.80229 87.390625 356.33093 curveto
+87.782549 356.85502 88.31803 357.11707 88.99707 357.11707 curveto
+89.666987 357.11707 90.197911 356.85274 90.589844 356.3241 curveto
+90.981765 355.79545 91.177728 355.0754 91.177734 354.16394 curveto
+91.177728 353.25704 90.981765 352.53927 90.589844 352.01062 curveto
+90.197911 351.47742 89.666987 351.21082 88.99707 351.21082 curveto
+88.99707 350.14441 moveto
+90.090815 350.14442 90.949864 350.49989 91.574219 351.21082 curveto
+92.19856 351.92176 92.510734 352.90613 92.510742 354.16394 curveto
+92.510734 355.4172 92.19856 356.40157 91.574219 357.11707 curveto
+90.949864 357.828 90.090815 358.18347 88.99707 358.18347 curveto
+87.89876 358.18347 87.037433 357.828 86.413086 357.11707 curveto
+85.793293 356.40157 85.483398 355.4172 85.483398 354.16394 curveto
+85.483398 352.90613 85.793293 351.92176 86.413086 351.21082 curveto
+87.037433 350.49989 87.89876 350.14442 88.99707 350.14441 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+94.390625 347.36218 moveto
+95.484375 347.36218 lineto
+96.167966 348.43771 96.678382 349.49045 97.015625 350.52039 curveto
+97.357418 351.55034 97.528316 352.57345 97.52832 353.58972 curveto
+97.528316 354.61056 97.357418 355.63823 97.015625 356.67273 curveto
+96.678382 357.70723 96.167966 358.75997 95.484375 359.83093 curveto
+94.390625 359.83093 lineto
+94.996743 358.78731 95.447914 357.75053 95.744141 356.72058 curveto
+96.044919 355.68608 96.19531 354.64246 96.195312 353.58972 curveto
+96.19531 352.53699 96.044919 351.49793 95.744141 350.47253 curveto
+95.447914 349.44715 94.996743 348.41037 94.390625 347.36218 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+102.34082 348.36218 moveto
+101.73014 349.41037 101.27669 350.44715 100.98047 351.47253 curveto
+100.68424 352.49793 100.53613 353.53699 100.53613 354.58972 curveto
+100.53613 355.64246 100.68424 356.68608 100.98047 357.72058 curveto
+101.28125 358.75053 101.7347 359.78731 102.34082 360.83093 curveto
+101.24707 360.83093 lineto
+100.56347 359.75997 100.05078 358.70723 99.708984 357.67273 curveto
+99.371743 356.63823 99.203124 355.61056 99.203125 354.58972 curveto
+99.203124 353.57345 99.371743 352.55034 99.708984 351.52039 curveto
+100.04622 350.49045 100.55892 349.43771 101.24707 348.36218 curveto
+102.34082 348.36218 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+108.75977 349.9823 moveto
+105.27344 355.43054 lineto
+108.75977 355.43054 lineto
+108.75977 349.9823 lineto
+108.39746 348.77917 moveto
+110.13379 348.77917 lineto
+110.13379 355.43054 lineto
+111.58984 355.43054 lineto
+111.58984 356.57898 lineto
+110.13379 356.57898 lineto
+110.13379 358.98523 lineto
+108.75977 358.98523 lineto
+108.75977 356.57898 lineto
+104.15234 356.57898 lineto
+104.15234 355.24597 lineto
+108.39746 348.77917 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+114.02344 357.2489 moveto
+115.46582 357.2489 lineto
+115.46582 358.42468 lineto
+114.34473 360.61218 lineto
+113.46289 360.61218 lineto
+114.02344 358.42468 lineto
+114.02344 357.2489 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+122.13086 349.9823 moveto
+118.64453 355.43054 lineto
+122.13086 355.43054 lineto
+122.13086 349.9823 lineto
+121.76855 348.77917 moveto
+123.50488 348.77917 lineto
+123.50488 355.43054 lineto
+124.96094 355.43054 lineto
+124.96094 356.57898 lineto
+123.50488 356.57898 lineto
+123.50488 358.98523 lineto
+122.13086 358.98523 lineto
+122.13086 356.57898 lineto
+117.52344 356.57898 lineto
+117.52344 355.24597 lineto
+121.76855 348.77917 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+127.39453 357.2489 moveto
+128.83691 357.2489 lineto
+128.83691 358.42468 lineto
+127.71582 360.61218 lineto
+126.83398 360.61218 lineto
+127.39453 358.42468 lineto
+127.39453 357.2489 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+134.49707 352.21082 moveto
+133.82259 352.21082 133.28938 352.47514 132.89746 353.00378 curveto
+132.50553 353.52788 132.30957 354.24793 132.30957 355.16394 curveto
+132.30957 356.07996 132.50325 356.80229 132.89062 357.33093 curveto
+133.28255 357.85502 133.81803 358.11707 134.49707 358.11707 curveto
+135.16699 358.11707 135.69791 357.85274 136.08984 357.3241 curveto
+136.48176 356.79545 136.67773 356.0754 136.67773 355.16394 curveto
+136.67773 354.25704 136.48176 353.53927 136.08984 353.01062 curveto
+135.69791 352.47742 135.16699 352.21082 134.49707 352.21082 curveto
+134.49707 351.14441 moveto
+135.59081 351.14442 136.44986 351.49989 137.07422 352.21082 curveto
+137.69856 352.92176 138.01073 353.90613 138.01074 355.16394 curveto
+138.01073 356.4172 137.69856 357.40157 137.07422 358.11707 curveto
+136.44986 358.828 135.59081 359.18347 134.49707 359.18347 curveto
+133.39876 359.18347 132.53743 358.828 131.91309 358.11707 curveto
+131.29329 357.40157 130.9834 356.4172 130.9834 355.16394 curveto
+130.9834 353.90613 131.29329 352.92176 131.91309 352.21082 curveto
+132.53743 351.49989 133.39876 351.14442 134.49707 351.14441 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+139.89062 348.36218 moveto
+140.98438 348.36218 lineto
+141.66797 349.43771 142.17838 350.49045 142.51562 351.52039 curveto
+142.85742 352.55034 143.02832 353.57345 143.02832 354.58972 curveto
+143.02832 355.61056 142.85742 356.63823 142.51562 357.67273 curveto
+142.17838 358.70723 141.66797 359.75997 140.98438 360.83093 curveto
+139.89062 360.83093 lineto
+140.49674 359.78731 140.94791 358.75053 141.24414 357.72058 curveto
+141.54492 356.68608 141.69531 355.64246 141.69531 354.58972 curveto
+141.69531 353.53699 141.54492 352.49793 141.24414 351.47253 curveto
+140.94791 350.44715 140.49674 349.41037 139.89062 348.36218 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+27.34082 371.86218 moveto
+26.730139 372.91037 26.276689 373.94715 25.980469 374.97253 curveto
+25.684242 375.99793 25.53613 377.03699 25.536133 378.08972 curveto
+25.53613 379.14246 25.684242 380.18608 25.980469 381.22058 curveto
+26.281247 382.25053 26.734697 383.28731 27.34082 384.33093 curveto
+26.24707 384.33093 lineto
+25.563474 383.25997 25.050779 382.20723 24.708984 381.17273 curveto
+24.371743 380.13823 24.203124 379.11056 24.203125 378.08972 curveto
+24.203124 377.07345 24.371743 376.05034 24.708984 375.02039 curveto
+25.046222 373.99045 25.558917 372.93771 26.24707 371.86218 curveto
+27.34082 371.86218 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+29.979492 372.27917 moveto
+35.400391 372.27917 lineto
+35.400391 373.44128 lineto
+31.244141 373.44128 lineto
+31.244141 375.94324 lineto
+31.444658 375.87488 31.645179 375.82475 31.845703 375.79285 curveto
+32.04622 375.7564 32.246741 375.73817 32.447266 375.73816 curveto
+33.586583 375.73817 34.488926 376.05034 35.154297 376.67468 curveto
+35.819654 377.29904 36.152336 378.14441 36.152344 379.21082 curveto
+36.152336 380.30912 35.81054 381.16362 35.126953 381.77429 curveto
+34.443353 382.38041 33.479487 382.68347 32.235352 382.68347 curveto
+31.806963 382.68347 31.369463 382.64701 30.922852 382.5741 curveto
+30.480792 382.50118 30.022785 382.39181 29.548828 382.24597 curveto
+29.548828 380.85828 lineto
+29.958983 381.08159 30.382811 381.24793 30.820312 381.3573 curveto
+31.25781 381.46668 31.720374 381.52136 32.208008 381.52136 curveto
+32.996415 381.52136 33.620763 381.31401 34.081055 380.89929 curveto
+34.541335 380.48458 34.771478 379.92176 34.771484 379.21082 curveto
+34.771478 378.49988 34.541335 377.93706 34.081055 377.52234 curveto
+33.620763 377.10763 32.996415 376.90027 32.208008 376.90027 curveto
+31.838864 376.90027 31.469724 376.94129 31.100586 377.02332 curveto
+30.736 377.10535 30.362303 377.23296 29.979492 377.40613 curveto
+29.979492 372.27917 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+39.023438 380.7489 moveto
+40.46582 380.7489 lineto
+40.46582 381.92468 lineto
+39.344727 384.11218 lineto
+38.462891 384.11218 lineto
+39.023438 381.92468 lineto
+39.023438 380.7489 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+43.350586 372.27917 moveto
+48.771484 372.27917 lineto
+48.771484 373.44128 lineto
+44.615234 373.44128 lineto
+44.615234 375.94324 lineto
+44.815752 375.87488 45.016273 375.82475 45.216797 375.79285 curveto
+45.417314 375.7564 45.617835 375.73817 45.818359 375.73816 curveto
+46.957677 375.73817 47.86002 376.05034 48.525391 376.67468 curveto
+49.190748 377.29904 49.52343 378.14441 49.523438 379.21082 curveto
+49.52343 380.30912 49.181633 381.16362 48.498047 381.77429 curveto
+47.814447 382.38041 46.850581 382.68347 45.606445 382.68347 curveto
+45.178057 382.68347 44.740557 382.64701 44.293945 382.5741 curveto
+43.851886 382.50118 43.393879 382.39181 42.919922 382.24597 curveto
+42.919922 380.85828 lineto
+43.330077 381.08159 43.753904 381.24793 44.191406 381.3573 curveto
+44.628903 381.46668 45.091468 381.52136 45.579102 381.52136 curveto
+46.367508 381.52136 46.991857 381.31401 47.452148 380.89929 curveto
+47.912429 380.48458 48.142572 379.92176 48.142578 379.21082 curveto
+48.142572 378.49988 47.912429 377.93706 47.452148 377.52234 curveto
+46.991857 377.10763 46.367508 376.90027 45.579102 376.90027 curveto
+45.209958 376.90027 44.840817 376.94129 44.47168 377.02332 curveto
+44.107094 377.10535 43.733397 377.23296 43.350586 377.40613 curveto
+43.350586 372.27917 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+52.394531 380.7489 moveto
+53.836914 380.7489 lineto
+53.836914 381.92468 lineto
+52.71582 384.11218 lineto
+51.833984 384.11218 lineto
+52.394531 381.92468 lineto
+52.394531 380.7489 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+59.49707 375.71082 moveto
+58.822588 375.71082 58.289385 375.97514 57.897461 376.50378 curveto
+57.505532 377.02788 57.309568 377.74793 57.30957 378.66394 curveto
+57.309568 379.57996 57.503253 380.30229 57.890625 380.83093 curveto
+58.282549 381.35502 58.81803 381.61707 59.49707 381.61707 curveto
+60.166987 381.61707 60.697911 381.35274 61.089844 380.8241 curveto
+61.481765 380.29545 61.677728 379.5754 61.677734 378.66394 curveto
+61.677728 377.75704 61.481765 377.03927 61.089844 376.51062 curveto
+60.697911 375.97742 60.166987 375.71082 59.49707 375.71082 curveto
+59.49707 374.64441 moveto
+60.590815 374.64442 61.449864 374.99989 62.074219 375.71082 curveto
+62.69856 376.42176 63.010734 377.40613 63.010742 378.66394 curveto
+63.010734 379.9172 62.69856 380.90157 62.074219 381.61707 curveto
+61.449864 382.328 60.590815 382.68347 59.49707 382.68347 curveto
+58.39876 382.68347 57.537433 382.328 56.913086 381.61707 curveto
+56.293293 380.90157 55.983398 379.9172 55.983398 378.66394 curveto
+55.983398 377.40613 56.293293 376.42176 56.913086 375.71082 curveto
+57.537433 374.99989 58.39876 374.64442 59.49707 374.64441 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+64.890625 371.86218 moveto
+65.984375 371.86218 lineto
+66.667966 372.93771 67.178382 373.99045 67.515625 375.02039 curveto
+67.857418 376.05034 68.028316 377.07345 68.02832 378.08972 curveto
+68.028316 379.11056 67.857418 380.13823 67.515625 381.17273 curveto
+67.178382 382.20723 66.667966 383.25997 65.984375 384.33093 curveto
+64.890625 384.33093 lineto
+65.496743 383.28731 65.947914 382.25053 66.244141 381.22058 curveto
+66.544919 380.18608 66.69531 379.14246 66.695312 378.08972 curveto
+66.69531 377.03699 66.544919 375.99793 66.244141 374.97253 curveto
+65.947914 373.94715 65.496743 372.91037 64.890625 371.86218 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+75.84082 370.86218 moveto
+75.230139 371.91037 74.776689 372.94715 74.480469 373.97253 curveto
+74.184242 374.99793 74.03613 376.03699 74.036133 377.08972 curveto
+74.03613 378.14246 74.184242 379.18608 74.480469 380.22058 curveto
+74.781247 381.25053 75.234697 382.28731 75.84082 383.33093 curveto
+74.74707 383.33093 lineto
+74.063474 382.25997 73.550779 381.20723 73.208984 380.17273 curveto
+72.871743 379.13823 72.703124 378.11056 72.703125 377.08972 curveto
+72.703124 376.07345 72.871743 375.05034 73.208984 374.02039 curveto
+73.546222 372.99045 74.058917 371.93771 74.74707 370.86218 curveto
+75.84082 370.86218 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+81.589844 375.83191 moveto
+80.970048 375.83191 80.477861 376.04383 80.113281 376.46765 curveto
+79.753252 376.89148 79.57324 377.47254 79.573242 378.21082 curveto
+79.57324 378.94454 79.753252 379.5256 80.113281 379.95398 curveto
+80.477861 380.37781 80.970048 380.58972 81.589844 380.58972 curveto
+82.20963 380.58972 82.699539 380.37781 83.05957 379.95398 curveto
+83.424147 379.5256 83.606439 378.94454 83.606445 378.21082 curveto
+83.606439 377.47254 83.424147 376.89148 83.05957 376.46765 curveto
+82.699539 376.04383 82.20963 375.83191 81.589844 375.83191 curveto
+84.331055 371.50476 moveto
+84.331055 372.76257 lineto
+83.984694 372.59852 83.633782 372.47319 83.27832 372.3866 curveto
+82.927403 372.30002 82.57877 372.25672 82.232422 372.25671 curveto
+81.320959 372.25672 80.623694 372.56434 80.140625 373.17957 curveto
+79.662107 373.79481 79.388669 374.72449 79.320312 375.96863 curveto
+79.58919 375.57215 79.926429 375.26909 80.332031 375.05945 curveto
+80.737626 374.84526 81.184241 374.73817 81.671875 374.73816 curveto
+82.69726 374.73817 83.506178 375.05034 84.098633 375.67468 curveto
+84.69563 376.29448 84.994133 377.13986 84.994141 378.21082 curveto
+84.994133 379.25899 84.684237 380.09981 84.064453 380.73328 curveto
+83.444655 381.36674 82.619786 381.68347 81.589844 381.68347 curveto
+80.409502 381.68347 79.507159 381.2323 78.882812 380.32996 curveto
+78.258462 379.42306 77.946288 378.11056 77.946289 376.39246 curveto
+77.946288 374.77918 78.3291 373.49403 79.094727 372.53699 curveto
+79.860349 371.57541 80.888017 371.09461 82.177734 371.0946 curveto
+82.524083 371.09461 82.872715 371.12879 83.223633 371.19714 curveto
+83.579095 371.26551 83.948235 371.36805 84.331055 371.50476 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+87.523438 379.7489 moveto
+88.96582 379.7489 lineto
+88.96582 380.92468 lineto
+87.844727 383.11218 lineto
+86.962891 383.11218 lineto
+87.523438 380.92468 lineto
+87.523438 379.7489 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+94.960938 375.83191 moveto
+94.341142 375.83191 93.848955 376.04383 93.484375 376.46765 curveto
+93.124346 376.89148 92.944333 377.47254 92.944336 378.21082 curveto
+92.944333 378.94454 93.124346 379.5256 93.484375 379.95398 curveto
+93.848955 380.37781 94.341142 380.58972 94.960938 380.58972 curveto
+95.580724 380.58972 96.070632 380.37781 96.430664 379.95398 curveto
+96.795241 379.5256 96.977532 378.94454 96.977539 378.21082 curveto
+96.977532 377.47254 96.795241 376.89148 96.430664 376.46765 curveto
+96.070632 376.04383 95.580724 375.83191 94.960938 375.83191 curveto
+97.702148 371.50476 moveto
+97.702148 372.76257 lineto
+97.355787 372.59852 97.004876 372.47319 96.649414 372.3866 curveto
+96.298497 372.30002 95.949864 372.25672 95.603516 372.25671 curveto
+94.692053 372.25672 93.994788 372.56434 93.511719 373.17957 curveto
+93.0332 373.79481 92.759763 374.72449 92.691406 375.96863 curveto
+92.960284 375.57215 93.297523 375.26909 93.703125 375.05945 curveto
+94.10872 374.84526 94.555334 374.73817 95.042969 374.73816 curveto
+96.068354 374.73817 96.877272 375.05034 97.469727 375.67468 curveto
+98.066724 376.29448 98.365226 377.13986 98.365234 378.21082 curveto
+98.365226 379.25899 98.055331 380.09981 97.435547 380.73328 curveto
+96.815749 381.36674 95.99088 381.68347 94.960938 381.68347 curveto
+93.780596 381.68347 92.878253 381.2323 92.253906 380.32996 curveto
+91.629556 379.42306 91.317382 378.11056 91.317383 376.39246 curveto
+91.317382 374.77918 91.700194 373.49403 92.46582 372.53699 curveto
+93.231442 371.57541 94.259111 371.09461 95.548828 371.0946 curveto
+95.895177 371.09461 96.243809 371.12879 96.594727 371.19714 curveto
+96.950189 371.26551 97.319329 371.36805 97.702148 371.50476 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+100.89453 379.7489 moveto
+102.33691 379.7489 lineto
+102.33691 380.92468 lineto
+101.21582 383.11218 lineto
+100.33398 383.11218 lineto
+100.89453 380.92468 lineto
+100.89453 379.7489 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+110.06836 377.56824 moveto
+110.06835 376.65678 109.87923 375.9504 109.50098 375.4491 curveto
+109.12727 374.9478 108.60091 374.69715 107.92188 374.69714 curveto
+107.24739 374.69715 106.72103 374.9478 106.34277 375.4491 curveto
+105.96907 375.9504 105.78222 376.65678 105.78223 377.56824 curveto
+105.78222 378.47514 105.96907 379.17924 106.34277 379.68054 curveto
+106.72103 380.18185 107.24739 380.4325 107.92188 380.4325 curveto
+108.60091 380.4325 109.12727 380.18185 109.50098 379.68054 curveto
+109.87923 379.17924 110.06835 378.47514 110.06836 377.56824 curveto
+111.32617 380.53503 moveto
+111.32616 381.83842 111.03678 382.80684 110.45801 383.44031 curveto
+109.87923 384.07833 108.99283 384.39734 107.79883 384.39734 curveto
+107.35677 384.39734 106.93978 384.36316 106.54785 384.2948 curveto
+106.15592 384.23099 105.77539 384.13073 105.40625 383.99402 curveto
+105.40625 382.77039 lineto
+105.77539 382.97091 106.13997 383.11902 106.5 383.21472 curveto
+106.86002 383.31042 107.22688 383.35827 107.60059 383.35828 curveto
+108.42545 383.35827 109.04296 383.1418 109.45312 382.70886 curveto
+109.86328 382.28048 110.06835 381.63106 110.06836 380.76062 curveto
+110.06836 380.13855 lineto
+109.80859 380.58972 109.47591 380.92696 109.07031 381.15027 curveto
+108.66471 381.37358 108.17936 381.48523 107.61426 381.48523 curveto
+106.67545 381.48523 105.91894 381.12748 105.34473 380.41199 curveto
+104.77051 379.69649 104.4834 378.74858 104.4834 377.56824 curveto
+104.4834 376.38335 104.77051 375.43315 105.34473 374.71765 curveto
+105.91894 374.00216 106.67545 373.64442 107.61426 373.64441 curveto
+108.17936 373.64442 108.66471 373.75607 109.07031 373.97937 curveto
+109.47591 374.20268 109.80859 374.53992 110.06836 374.99109 curveto
+110.06836 373.82898 lineto
+111.32617 373.82898 lineto
+111.32617 380.53503 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+113.71875 370.86218 moveto
+114.8125 370.86218 lineto
+115.49609 371.93771 116.00651 372.99045 116.34375 374.02039 curveto
+116.68554 375.05034 116.85644 376.07345 116.85645 377.08972 curveto
+116.85644 378.11056 116.68554 379.13823 116.34375 380.17273 curveto
+116.00651 381.20723 115.49609 382.25997 114.8125 383.33093 curveto
+113.71875 383.33093 lineto
+114.32487 382.28731 114.77604 381.25053 115.07227 380.22058 curveto
+115.37304 379.18608 115.52343 378.14246 115.52344 377.08972 curveto
+115.52343 376.03699 115.37304 374.99793 115.07227 373.97253 curveto
+114.77604 372.94715 114.32487 371.91037 113.71875 370.86218 curveto
+fill
+grestore
+gsave [1.04082 0 0 0.999696 -220.2817 5.106745] concat
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+349.5 351.36218 moveto
+349.5 378.68618 319.484 400.86218 282.5 400.86218 curveto
+245.516 400.86218 215.5 378.68618 215.5 351.36218 curveto
+215.5 324.03818 245.516 301.86218 282.5 301.86218 curveto
+319.484 301.86218 349.5 324.03818 349.5 351.36218 curveto
+closepath
+stroke
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+66.874023 311.95789 moveto
+68.254883 311.95789 lineto
+68.254883 322.16394 lineto
+66.874023 322.16394 lineto
+66.874023 311.95789 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+75.829102 314.73328 moveto
+75.829102 315.92273 lineto
+75.473627 315.74044 75.104487 315.60373 74.72168 315.51257 curveto
+74.338862 315.42143 73.942378 315.37586 73.532227 315.37585 curveto
+72.907874 315.37586 72.438474 315.47156 72.124023 315.66296 curveto
+71.814125 315.85438 71.659178 316.14149 71.65918 316.52429 curveto
+71.659178 316.81596 71.770831 317.04611 71.994141 317.21472 curveto
+72.217445 317.37879 72.666338 317.53602 73.34082 317.6864 curveto
+73.771484 317.7821 lineto
+74.664709 317.97351 75.298171 318.24467 75.671875 318.59558 curveto
+76.050124 318.94194 76.239251 319.42729 76.239258 320.05164 curveto
+76.239251 320.76257 75.956699 321.3254 75.391602 321.74011 curveto
+74.831049 322.15483 74.058589 322.36218 73.074219 322.36218 curveto
+72.664059 322.36218 72.235674 322.32117 71.789062 322.23914 curveto
+71.347003 322.16166 70.879882 322.04317 70.387695 321.88367 curveto
+70.387695 320.58484 lineto
+70.852538 320.82638 71.310545 321.00867 71.761719 321.13171 curveto
+72.212888 321.2502 72.659502 321.30945 73.101562 321.30945 curveto
+73.694006 321.30945 74.149735 321.20919 74.46875 321.00867 curveto
+74.787755 320.80359 74.94726 320.51648 74.947266 320.14734 curveto
+74.94726 319.80554 74.831049 319.5435 74.598633 319.36121 curveto
+74.370763 319.17892 73.867183 319.00346 73.087891 318.83484 curveto
+72.650391 318.7323 lineto
+71.871092 318.56824 71.308267 318.31759 70.961914 317.98035 curveto
+70.615559 317.63855 70.442382 317.17143 70.442383 316.57898 curveto
+70.442382 315.85893 70.69759 315.30294 71.208008 314.91101 curveto
+71.718422 314.51909 72.443031 314.32313 73.381836 314.32312 curveto
+73.846675 314.32313 74.284175 314.35731 74.694336 314.42566 curveto
+75.104487 314.49403 75.482742 314.59657 75.829102 314.73328 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+6.3125 439.27167 moveto
+5.7018192 440.31985 5.2483691 441.35664 4.9521484 442.38202 curveto
+4.6559218 443.40742 4.50781 444.44648 4.5078125 445.49921 curveto
+4.50781 446.55194 4.6559218 447.59556 4.9521484 448.63007 curveto
+5.2529264 449.66001 5.7063765 450.6968 6.3125 451.74042 curveto
+5.21875 451.74042 lineto
+4.5351537 450.66945 4.0224589 449.61672 3.6806641 448.58221 curveto
+3.3434231 447.54771 3.1748035 446.52004 3.1748047 445.49921 curveto
+3.1748035 444.48294 3.3434231 443.45982 3.6806641 442.42987 curveto
+4.0179016 441.39993 4.5305964 440.3472 5.21875 439.27167 curveto
+6.3125 439.27167 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+11.890625 440.59784 moveto
+11.179684 440.59785 10.644203 440.94876 10.28418 441.65057 curveto
+9.9287084 442.34785 9.7509743 443.3983 9.7509766 444.80194 curveto
+9.7509743 446.20103 9.9287084 447.25149 10.28418 447.95331 curveto
+10.644203 448.65057 11.179684 448.99921 11.890625 448.99921 curveto
+12.606115 448.99921 13.141596 448.65057 13.49707 447.95331 curveto
+13.85709 447.25149 14.037103 446.20103 14.037109 444.80194 curveto
+14.037103 443.3983 13.85709 442.34785 13.49707 441.65057 curveto
+13.141596 440.94876 12.606115 440.59785 11.890625 440.59784 curveto
+11.890625 439.50409 moveto
+13.0345 439.5041 13.90722 439.95755 14.508789 440.86444 curveto
+15.114901 441.76679 15.417961 443.07929 15.417969 444.80194 curveto
+15.417961 446.52004 15.114901 447.83254 14.508789 448.73944 curveto
+13.90722 449.64178 13.0345 450.09296 11.890625 450.09296 curveto
+10.746741 450.09296 9.8717424 449.64178 9.265625 448.73944 curveto
+8.6640613 447.83254 8.3632803 446.52004 8.3632812 444.80194 curveto
+8.3632803 443.07929 8.6640613 441.76679 9.265625 440.86444 curveto
+9.8717424 439.95755 10.746741 439.5041 11.890625 439.50409 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+17.995117 448.15839 moveto
+19.4375 448.15839 lineto
+19.4375 449.33417 lineto
+18.316406 451.52167 lineto
+17.43457 451.52167 lineto
+17.995117 449.33417 lineto
+17.995117 448.15839 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+25.261719 440.59784 moveto
+24.550778 440.59785 24.015296 440.94876 23.655273 441.65057 curveto
+23.299802 442.34785 23.122068 443.3983 23.12207 444.80194 curveto
+23.122068 446.20103 23.299802 447.25149 23.655273 447.95331 curveto
+24.015296 448.65057 24.550778 448.99921 25.261719 448.99921 curveto
+25.977208 448.99921 26.51269 448.65057 26.868164 447.95331 curveto
+27.228184 447.25149 27.408197 446.20103 27.408203 444.80194 curveto
+27.408197 443.3983 27.228184 442.34785 26.868164 441.65057 curveto
+26.51269 440.94876 25.977208 440.59785 25.261719 440.59784 curveto
+25.261719 439.50409 moveto
+26.405593 439.5041 27.278314 439.95755 27.879883 440.86444 curveto
+28.485995 441.76679 28.789055 443.07929 28.789062 444.80194 curveto
+28.789055 446.52004 28.485995 447.83254 27.879883 448.73944 curveto
+27.278314 449.64178 26.405593 450.09296 25.261719 450.09296 curveto
+24.117835 450.09296 23.242836 449.64178 22.636719 448.73944 curveto
+22.035155 447.83254 21.734374 446.52004 21.734375 444.80194 curveto
+21.734374 443.07929 22.035155 441.76679 22.636719 440.86444 curveto
+23.242836 439.95755 24.117835 439.5041 25.261719 439.50409 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+31.366211 448.15839 moveto
+32.808594 448.15839 lineto
+32.808594 449.33417 lineto
+31.6875 451.52167 lineto
+30.805664 451.52167 lineto
+31.366211 449.33417 lineto
+31.366211 448.15839 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+38.46875 443.1203 moveto
+37.794267 443.12031 37.261065 443.38463 36.869141 443.91327 curveto
+36.477211 444.43736 36.281248 445.15741 36.28125 446.07343 curveto
+36.281248 446.98944 36.474933 447.71177 36.862305 448.24042 curveto
+37.254229 448.76451 37.78971 449.02655 38.46875 449.02655 curveto
+39.138667 449.02655 39.669591 448.76223 40.061523 448.23358 curveto
+40.453444 447.70494 40.649408 446.98489 40.649414 446.07343 curveto
+40.649408 445.16653 40.453444 444.44876 40.061523 443.9201 curveto
+39.669591 443.38691 39.138667 443.12031 38.46875 443.1203 curveto
+38.46875 442.05389 moveto
+39.562495 442.0539 40.421543 442.40937 41.045898 443.1203 curveto
+41.67024 443.83124 41.982414 444.81562 41.982422 446.07343 curveto
+41.982414 447.32668 41.67024 448.31106 41.045898 449.02655 curveto
+40.421543 449.73749 39.562495 450.09296 38.46875 450.09296 curveto
+37.37044 450.09296 36.509112 449.73749 35.884766 449.02655 curveto
+35.264973 448.31106 34.955077 447.32668 34.955078 446.07343 curveto
+34.955077 444.81562 35.264973 443.83124 35.884766 443.1203 curveto
+36.509112 442.40937 37.37044 442.0539 38.46875 442.05389 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+43.862305 439.27167 moveto
+44.956055 439.27167 lineto
+45.639646 440.3472 46.150062 441.39993 46.487305 442.42987 curveto
+46.829097 443.45982 46.999996 444.48294 47 445.49921 curveto
+46.999996 446.52004 46.829097 447.54771 46.487305 448.58221 curveto
+46.150062 449.61672 45.639646 450.66945 44.956055 451.74042 curveto
+43.862305 451.74042 lineto
+44.468423 450.6968 44.919594 449.66001 45.21582 448.63007 curveto
+45.516599 447.59556 45.666989 446.55194 45.666992 445.49921 curveto
+45.666989 444.44648 45.516599 443.40742 45.21582 442.38202 curveto
+44.919594 441.35664 44.468423 440.31985 43.862305 439.27167 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+51.951172 439.27167 moveto
+51.340491 440.31985 50.887041 441.35664 50.59082 442.38202 curveto
+50.294594 443.40742 50.146482 444.44648 50.146484 445.49921 curveto
+50.146482 446.55194 50.294594 447.59556 50.59082 448.63007 curveto
+50.891598 449.66001 51.345048 450.6968 51.951172 451.74042 curveto
+50.857422 451.74042 lineto
+50.173826 450.66945 49.661131 449.61672 49.319336 448.58221 curveto
+48.982095 447.54771 48.813475 446.52004 48.813477 445.49921 curveto
+48.813475 444.48294 48.982095 443.45982 49.319336 442.42987 curveto
+49.656573 441.39993 50.169268 440.3472 50.857422 439.27167 curveto
+51.951172 439.27167 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+54.81543 448.7326 moveto
+57.071289 448.7326 lineto
+57.071289 440.94647 lineto
+54.617188 441.43866 lineto
+54.617188 440.18085 lineto
+57.057617 439.68866 lineto
+58.438477 439.68866 lineto
+58.438477 448.7326 lineto
+60.694336 448.7326 lineto
+60.694336 449.89471 lineto
+54.81543 449.89471 lineto
+54.81543 448.7326 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+63.633789 448.15839 moveto
+65.076172 448.15839 lineto
+65.076172 449.33417 lineto
+63.955078 451.52167 lineto
+63.073242 451.52167 lineto
+63.633789 449.33417 lineto
+63.633789 448.15839 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+68.186523 448.7326 moveto
+70.442383 448.7326 lineto
+70.442383 440.94647 lineto
+67.988281 441.43866 lineto
+67.988281 440.18085 lineto
+70.428711 439.68866 lineto
+71.80957 439.68866 lineto
+71.80957 448.7326 lineto
+74.06543 448.7326 lineto
+74.06543 449.89471 lineto
+68.186523 449.89471 lineto
+68.186523 448.7326 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+77.004883 448.15839 moveto
+78.447266 448.15839 lineto
+78.447266 449.33417 lineto
+77.326172 451.52167 lineto
+76.444336 451.52167 lineto
+77.004883 449.33417 lineto
+77.004883 448.15839 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+84.107422 443.1203 moveto
+83.432939 443.12031 82.899737 443.38463 82.507812 443.91327 curveto
+82.115883 444.43736 81.91992 445.15741 81.919922 446.07343 curveto
+81.91992 446.98944 82.113604 447.71177 82.500977 448.24042 curveto
+82.892901 448.76451 83.428382 449.02655 84.107422 449.02655 curveto
+84.777339 449.02655 85.308263 448.76223 85.700195 448.23358 curveto
+86.092116 447.70494 86.288079 446.98489 86.288086 446.07343 curveto
+86.288079 445.16653 86.092116 444.44876 85.700195 443.9201 curveto
+85.308263 443.38691 84.777339 443.12031 84.107422 443.1203 curveto
+84.107422 442.05389 moveto
+85.201166 442.0539 86.060215 442.40937 86.68457 443.1203 curveto
+87.308912 443.83124 87.621086 444.81562 87.621094 446.07343 curveto
+87.621086 447.32668 87.308912 448.31106 86.68457 449.02655 curveto
+86.060215 449.73749 85.201166 450.09296 84.107422 450.09296 curveto
+83.009111 450.09296 82.147784 449.73749 81.523438 449.02655 curveto
+80.903645 448.31106 80.593749 447.32668 80.59375 446.07343 curveto
+80.593749 444.81562 80.903645 443.83124 81.523438 443.1203 curveto
+82.147784 442.40937 83.009111 442.0539 84.107422 442.05389 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+89.500977 439.27167 moveto
+90.594727 439.27167 lineto
+91.278317 440.3472 91.788734 441.39993 92.125977 442.42987 curveto
+92.467769 443.45982 92.638668 444.48294 92.638672 445.49921 curveto
+92.638668 446.52004 92.467769 447.54771 92.125977 448.58221 curveto
+91.788734 449.61672 91.278317 450.66945 90.594727 451.74042 curveto
+89.500977 451.74042 lineto
+90.107095 450.6968 90.558266 449.66001 90.854492 448.63007 curveto
+91.155271 447.59556 91.305661 446.55194 91.305664 445.49921 curveto
+91.305661 444.44648 91.155271 443.40742 90.854492 442.38202 curveto
+90.558266 441.35664 90.107095 440.31985 89.500977 439.27167 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+51.951172 458.80682 moveto
+51.340491 459.85501 50.887041 460.89179 50.59082 461.91718 curveto
+50.294594 462.94257 50.146482 463.98163 50.146484 465.03436 curveto
+50.146482 466.0871 50.294594 467.13072 50.59082 468.16522 curveto
+50.891598 469.19517 51.345048 470.23195 51.951172 471.27557 curveto
+50.857422 471.27557 lineto
+50.173826 470.20461 49.661131 469.15188 49.319336 468.11737 curveto
+48.982095 467.08287 48.813475 466.0552 48.813477 465.03436 curveto
+48.813475 464.01809 48.982095 462.99498 49.319336 461.96503 curveto
+49.656573 460.93509 50.169268 459.88235 50.857422 458.80682 curveto
+51.951172 458.80682 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+54.589844 459.22382 moveto
+60.010742 459.22382 lineto
+60.010742 460.38593 lineto
+55.854492 460.38593 lineto
+55.854492 462.88788 lineto
+56.05501 462.81953 56.255531 462.7694 56.456055 462.73749 curveto
+56.656572 462.70104 56.857093 462.68281 57.057617 462.6828 curveto
+58.196935 462.68281 59.099278 462.99498 59.764648 463.61932 curveto
+60.430006 464.24368 60.762688 465.08905 60.762695 466.15546 curveto
+60.762688 467.25377 60.420891 468.10826 59.737305 468.71893 curveto
+59.053705 469.32505 58.089839 469.62811 56.845703 469.62811 curveto
+56.417314 469.62811 55.979815 469.59165 55.533203 469.51874 curveto
+55.091144 469.44582 54.633136 469.33645 54.15918 469.19061 curveto
+54.15918 467.80292 lineto
+54.569334 468.02623 54.993162 468.19257 55.430664 468.30194 curveto
+55.868161 468.41132 56.330726 468.466 56.818359 468.466 curveto
+57.606766 468.466 58.231115 468.25865 58.691406 467.84393 curveto
+59.151687 467.42922 59.38183 466.8664 59.381836 466.15546 curveto
+59.38183 465.44452 59.151687 464.8817 58.691406 464.46698 curveto
+58.231115 464.05227 57.606766 463.84492 56.818359 463.84491 curveto
+56.449215 463.84492 56.080075 463.88593 55.710938 463.96796 curveto
+55.346352 464.04999 54.972654 464.1776 54.589844 464.35077 curveto
+54.589844 459.22382 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+63.633789 467.69354 moveto
+65.076172 467.69354 lineto
+65.076172 468.86932 lineto
+63.955078 471.05682 lineto
+63.073242 471.05682 lineto
+63.633789 468.86932 lineto
+63.633789 467.69354 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+71.741211 460.42694 moveto
+68.254883 465.87518 lineto
+71.741211 465.87518 lineto
+71.741211 460.42694 lineto
+71.378906 459.22382 moveto
+73.115234 459.22382 lineto
+73.115234 465.87518 lineto
+74.571289 465.87518 lineto
+74.571289 467.02362 lineto
+73.115234 467.02362 lineto
+73.115234 469.42987 lineto
+71.741211 469.42987 lineto
+71.741211 467.02362 lineto
+67.133789 467.02362 lineto
+67.133789 465.69061 lineto
+71.378906 459.22382 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+77.004883 467.69354 moveto
+78.447266 467.69354 lineto
+78.447266 468.86932 lineto
+77.326172 471.05682 lineto
+76.444336 471.05682 lineto
+77.004883 468.86932 lineto
+77.004883 467.69354 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+86.178711 465.51288 moveto
+86.178705 464.60142 85.989577 463.89505 85.611328 463.39374 curveto
+85.237625 462.89244 84.711258 462.64179 84.032227 462.64178 curveto
+83.357744 462.64179 82.831377 462.89244 82.453125 463.39374 curveto
+82.079425 463.89505 81.892576 464.60142 81.892578 465.51288 curveto
+81.892576 466.41978 82.079425 467.12388 82.453125 467.62518 curveto
+82.831377 468.12649 83.357744 468.37714 84.032227 468.37714 curveto
+84.711258 468.37714 85.237625 468.12649 85.611328 467.62518 curveto
+85.989577 467.12388 86.178705 466.41978 86.178711 465.51288 curveto
+87.436523 468.47968 moveto
+87.436516 469.78306 87.147128 470.75148 86.568359 471.38495 curveto
+85.989577 472.02297 85.103185 472.34198 83.90918 472.34198 curveto
+83.467119 472.34198 83.050127 472.3078 82.658203 472.23944 curveto
+82.266274 472.17564 81.88574 472.07538 81.516602 471.93866 curveto
+81.516602 470.71503 lineto
+81.88574 470.91555 82.250323 471.06366 82.610352 471.15936 curveto
+82.970374 471.25506 83.337236 471.30292 83.710938 471.30292 curveto
+84.535803 471.30292 85.153315 471.08644 85.563477 470.6535 curveto
+85.973627 470.22512 86.178705 469.5757 86.178711 468.70526 curveto
+86.178711 468.08319 lineto
+85.918939 468.53436 85.586257 468.8716 85.180664 469.09491 curveto
+84.77506 469.31822 84.289709 469.42987 83.724609 469.42987 curveto
+82.785804 469.42987 82.029295 469.07212 81.455078 468.35663 curveto
+80.880858 467.64114 80.593749 466.69322 80.59375 465.51288 curveto
+80.593749 464.32799 80.880858 463.37779 81.455078 462.66229 curveto
+82.029295 461.94681 82.785804 461.58906 83.724609 461.58905 curveto
+84.289709 461.58906 84.77506 461.70071 85.180664 461.92401 curveto
+85.586257 462.14733 85.918939 462.48457 86.178711 462.93573 curveto
+86.178711 461.77362 lineto
+87.436523 461.77362 lineto
+87.436523 468.47968 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+89.829102 458.80682 moveto
+90.922852 458.80682 lineto
+91.606442 459.88235 92.116859 460.93509 92.454102 461.96503 curveto
+92.795894 462.99498 92.966793 464.01809 92.966797 465.03436 curveto
+92.966793 466.0552 92.795894 467.08287 92.454102 468.11737 curveto
+92.116859 469.15188 91.606442 470.20461 90.922852 471.27557 curveto
+89.829102 471.27557 lineto
+90.43522 470.23195 90.886391 469.19517 91.182617 468.16522 curveto
+91.483396 467.13072 91.633786 466.0871 91.633789 465.03436 curveto
+91.633786 463.98163 91.483396 462.94257 91.182617 461.91718 curveto
+90.886391 460.89179 90.43522 459.85501 89.829102 458.80682 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+97.405273 439.73846 moveto
+96.794593 440.78665 96.341143 441.82343 96.044922 442.84882 curveto
+95.748695 443.87421 95.600583 444.91327 95.600586 445.966 curveto
+95.600583 447.01874 95.748695 448.06236 96.044922 449.09686 curveto
+96.3457 450.12681 96.79915 451.16359 97.405273 452.20721 curveto
+96.311523 452.20721 lineto
+95.627927 451.13625 95.115232 450.08352 94.773438 449.04901 curveto
+94.436197 448.01451 94.267577 446.98684 94.267578 445.966 curveto
+94.267577 444.94973 94.436197 443.92662 94.773438 442.89667 curveto
+95.110675 441.86673 95.62337 440.81399 96.311523 439.73846 curveto
+97.405273 439.73846 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+101.21973 449.1994 moveto
+106.03906 449.1994 lineto
+106.03906 450.36151 lineto
+99.558594 450.36151 lineto
+99.558594 449.1994 lineto
+100.08268 448.65709 100.7959 447.9302 101.69824 447.01874 curveto
+102.60514 446.10273 103.1748 445.51256 103.40723 445.24823 curveto
+103.84928 444.75149 104.1569 444.33222 104.33008 443.99042 curveto
+104.50781 443.64407 104.59667 443.30455 104.59668 442.97186 curveto
+104.59667 442.42955 104.40527 441.9875 104.02246 441.64569 curveto
+103.6442 441.3039 103.14973 441.133 102.53906 441.133 curveto
+102.10612 441.133 101.64811 441.2082 101.16504 441.35858 curveto
+100.68652 441.50898 100.17383 441.73685 99.626953 442.04218 curveto
+99.626953 440.64764 lineto
+100.18294 440.42435 100.70247 440.25573 101.18555 440.14178 curveto
+101.66862 440.02786 102.11067 439.9709 102.51172 439.97089 curveto
+103.56901 439.9709 104.4121 440.23522 105.04102 440.76385 curveto
+105.66991 441.29251 105.98437 441.99889 105.98438 442.883 curveto
+105.98437 443.30227 105.90462 443.70104 105.74512 444.07928 curveto
+105.59016 444.45299 105.30533 444.89505 104.89062 445.40546 curveto
+104.77669 445.53762 104.41438 445.92043 103.80371 446.55389 curveto
+103.19303 447.1828 102.3317 448.06464 101.21973 449.1994 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+109.08789 448.62518 moveto
+110.53027 448.62518 lineto
+110.53027 449.80096 lineto
+109.40918 451.98846 lineto
+108.52734 451.98846 lineto
+109.08789 449.80096 lineto
+109.08789 448.62518 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+114.59082 449.1994 moveto
+119.41016 449.1994 lineto
+119.41016 450.36151 lineto
+112.92969 450.36151 lineto
+112.92969 449.1994 lineto
+113.45377 448.65709 114.16699 447.9302 115.06934 447.01874 curveto
+115.97623 446.10273 116.54589 445.51256 116.77832 445.24823 curveto
+117.22037 444.75149 117.52799 444.33222 117.70117 443.99042 curveto
+117.8789 443.64407 117.96777 443.30455 117.96777 442.97186 curveto
+117.96777 442.42955 117.77636 441.9875 117.39355 441.64569 curveto
+117.01529 441.3039 116.52083 441.133 115.91016 441.133 curveto
+115.47721 441.133 115.0192 441.2082 114.53613 441.35858 curveto
+114.05762 441.50898 113.54492 441.73685 112.99805 442.04218 curveto
+112.99805 440.64764 lineto
+113.55403 440.42435 114.07357 440.25573 114.55664 440.14178 curveto
+115.03971 440.02786 115.48177 439.9709 115.88281 439.97089 curveto
+116.9401 439.9709 117.7832 440.23522 118.41211 440.76385 curveto
+119.04101 441.29251 119.35546 441.99889 119.35547 442.883 curveto
+119.35546 443.30227 119.27571 443.70104 119.11621 444.07928 curveto
+118.96126 444.45299 118.67643 444.89505 118.26172 445.40546 curveto
+118.14778 445.53762 117.78548 445.92043 117.1748 446.55389 curveto
+116.56412 447.1828 115.7028 448.06464 114.59082 449.1994 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+122.45898 448.62518 moveto
+123.90137 448.62518 lineto
+123.90137 449.80096 lineto
+122.78027 451.98846 lineto
+121.89844 451.98846 lineto
+122.45898 449.80096 lineto
+122.45898 448.62518 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+129.56152 443.5871 moveto
+128.88704 443.5871 128.35384 443.85143 127.96191 444.38007 curveto
+127.56998 444.90416 127.37402 445.62421 127.37402 446.54022 curveto
+127.37402 447.45624 127.56771 448.17857 127.95508 448.70721 curveto
+128.347 449.2313 128.88248 449.49335 129.56152 449.49335 curveto
+130.23144 449.49335 130.76236 449.22903 131.1543 448.70038 curveto
+131.54622 448.17173 131.74218 447.45168 131.74219 446.54022 curveto
+131.74218 445.63333 131.54622 444.91555 131.1543 444.3869 curveto
+130.76236 443.85371 130.23144 443.5871 129.56152 443.5871 curveto
+129.56152 442.52069 moveto
+130.65527 442.5207 131.51432 442.87617 132.13867 443.5871 curveto
+132.76301 444.29804 133.07519 445.28241 133.0752 446.54022 curveto
+133.07519 447.79348 132.76301 448.77785 132.13867 449.49335 curveto
+131.51432 450.20428 130.65527 450.55975 129.56152 450.55975 curveto
+128.46321 450.55975 127.60189 450.20428 126.97754 449.49335 curveto
+126.35775 448.77785 126.04785 447.79348 126.04785 446.54022 curveto
+126.04785 445.28241 126.35775 444.29804 126.97754 443.5871 curveto
+127.60189 442.87617 128.46321 442.5207 129.56152 442.52069 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+134.95508 439.73846 moveto
+136.04883 439.73846 lineto
+136.73242 440.81399 137.24284 441.86673 137.58008 442.89667 curveto
+137.92187 443.92662 138.09277 444.94973 138.09277 445.966 curveto
+138.09277 446.98684 137.92187 448.01451 137.58008 449.04901 curveto
+137.24284 450.08352 136.73242 451.13625 136.04883 452.20721 curveto
+134.95508 452.20721 lineto
+135.5612 451.16359 136.01237 450.12681 136.30859 449.09686 curveto
+136.60937 448.06236 136.75976 447.01874 136.75977 445.966 curveto
+136.75976 444.91327 136.60937 443.87421 136.30859 442.84882 curveto
+136.01237 441.82343 135.5612 440.78665 134.95508 439.73846 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+5.1376953 458.27362 moveto
+4.5270145 459.32181 4.0735644 460.35859 3.7773438 461.38397 curveto
+3.4811171 462.40937 3.3330053 463.44843 3.3330078 464.50116 curveto
+3.3330053 465.5539 3.4811171 466.59752 3.7773438 467.63202 curveto
+4.0781217 468.66197 4.5315718 469.69875 5.1376953 470.74237 curveto
+4.0439453 470.74237 lineto
+3.360349 469.67141 2.8476542 468.61867 2.5058594 467.58417 curveto
+2.1686184 466.54966 1.9999988 465.522 2 464.50116 curveto
+1.9999988 463.48489 2.1686184 462.46178 2.5058594 461.43182 curveto
+2.8430969 460.40188 3.3557917 459.34915 4.0439453 458.27362 curveto
+5.1376953 458.27362 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+11.946289 463.39374 moveto
+12.60709 463.53502 13.122063 463.82896 13.491211 464.27557 curveto
+13.864901 464.72219 14.05175 465.27362 14.051758 465.92987 curveto
+14.05175 466.93703 13.705396 467.71633 13.012695 468.26776 curveto
+12.319981 468.81919 11.335607 469.09491 10.05957 469.09491 curveto
+9.6311815 469.09491 9.1891247 469.05162 8.7333984 468.96503 curveto
+8.2822245 468.883 7.8151026 468.75767 7.3320312 468.58905 curveto
+7.3320312 467.25604 lineto
+7.7148423 467.47935 8.1341127 467.64797 8.5898438 467.7619 curveto
+9.0455701 467.87584 9.5218066 467.9328 10.018555 467.9328 curveto
+10.884435 467.9328 11.542963 467.7619 11.994141 467.4201 curveto
+12.449864 467.07831 12.677728 466.58157 12.677734 465.92987 curveto
+12.677728 465.32831 12.465814 464.85891 12.041992 464.52167 curveto
+11.622716 464.17988 11.037105 464.00898 10.285156 464.00897 curveto
+9.0957031 464.00897 lineto
+9.0957031 462.87421 lineto
+10.339844 462.87421 lineto
+11.018875 462.87421 11.538406 462.73977 11.898438 462.47089 curveto
+12.258458 462.19746 12.43847 461.80553 12.438477 461.2951 curveto
+12.43847 460.77102 12.251622 460.36998 11.87793 460.09198 curveto
+11.508784 459.80944 10.97786 459.66816 10.285156 459.66815 curveto
+9.9068974 459.66816 9.5012988 459.70918 9.0683594 459.7912 curveto
+8.6354143 459.87324 8.1591778 460.00084 7.6396484 460.17401 curveto
+7.6396484 458.94354 lineto
+8.1637351 458.79772 8.6536434 458.68834 9.109375 458.61542 curveto
+9.5696582 458.54251 10.0026 458.50605 10.408203 458.50604 curveto
+11.456375 458.50605 12.285801 458.74531 12.896484 459.22382 curveto
+13.507154 459.69778 13.812492 460.34036 13.8125 461.15155 curveto
+13.812492 461.71666 13.650709 462.19518 13.327148 462.5871 curveto
+13.003574 462.97447 12.543288 463.24335 11.946289 463.39374 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+16.820312 467.16034 moveto
+18.262695 467.16034 lineto
+18.262695 468.33612 lineto
+17.141602 470.52362 lineto
+16.259766 470.52362 lineto
+16.820312 468.33612 lineto
+16.820312 467.16034 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+25.317383 463.39374 moveto
+25.978184 463.53502 26.493157 463.82896 26.862305 464.27557 curveto
+27.235995 464.72219 27.422844 465.27362 27.422852 465.92987 curveto
+27.422844 466.93703 27.07649 467.71633 26.383789 468.26776 curveto
+25.691075 468.81919 24.706701 469.09491 23.430664 469.09491 curveto
+23.002275 469.09491 22.560218 469.05162 22.104492 468.96503 curveto
+21.653318 468.883 21.186196 468.75767 20.703125 468.58905 curveto
+20.703125 467.25604 lineto
+21.085936 467.47935 21.505206 467.64797 21.960938 467.7619 curveto
+22.416664 467.87584 22.8929 467.9328 23.389648 467.9328 curveto
+24.255529 467.9328 24.914057 467.7619 25.365234 467.4201 curveto
+25.820957 467.07831 26.048822 466.58157 26.048828 465.92987 curveto
+26.048822 465.32831 25.836908 464.85891 25.413086 464.52167 curveto
+24.99381 464.17988 24.408198 464.00898 23.65625 464.00897 curveto
+22.466797 464.00897 lineto
+22.466797 462.87421 lineto
+23.710938 462.87421 lineto
+24.389969 462.87421 24.9095 462.73977 25.269531 462.47089 curveto
+25.629551 462.19746 25.809564 461.80553 25.80957 461.2951 curveto
+25.809564 460.77102 25.622715 460.36998 25.249023 460.09198 curveto
+24.879878 459.80944 24.348954 459.66816 23.65625 459.66815 curveto
+23.277991 459.66816 22.872393 459.70918 22.439453 459.7912 curveto
+22.006508 459.87324 21.530272 460.00084 21.010742 460.17401 curveto
+21.010742 458.94354 lineto
+21.534829 458.79772 22.024737 458.68834 22.480469 458.61542 curveto
+22.940752 458.54251 23.373694 458.50605 23.779297 458.50604 curveto
+24.827469 458.50605 25.656895 458.74531 26.267578 459.22382 curveto
+26.878248 459.69778 27.183586 460.34036 27.183594 461.15155 curveto
+27.183586 461.71666 27.021803 462.19518 26.698242 462.5871 curveto
+26.374668 462.97447 25.914382 463.24335 25.317383 463.39374 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+30.191406 467.16034 moveto
+31.633789 467.16034 lineto
+31.633789 468.33612 lineto
+30.512695 470.52362 lineto
+29.630859 470.52362 lineto
+30.191406 468.33612 lineto
+30.191406 467.16034 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+39.365234 464.97968 moveto
+39.365228 464.06822 39.176101 463.36184 38.797852 462.86053 curveto
+38.424148 462.35924 37.897782 462.10859 37.21875 462.10858 curveto
+36.544267 462.10859 36.017901 462.35924 35.639648 462.86053 curveto
+35.265948 463.36184 35.079099 464.06822 35.079102 464.97968 curveto
+35.079099 465.88658 35.265948 466.59068 35.639648 467.09198 curveto
+36.017901 467.59328 36.544267 467.84393 37.21875 467.84393 curveto
+37.897782 467.84393 38.424148 467.59328 38.797852 467.09198 curveto
+39.176101 466.59068 39.365228 465.88658 39.365234 464.97968 curveto
+40.623047 467.94647 moveto
+40.623039 469.24986 40.333652 470.21828 39.754883 470.85175 curveto
+39.176101 471.48976 38.289708 471.80877 37.095703 471.80878 curveto
+36.653642 471.80877 36.23665 471.77459 35.844727 471.70624 curveto
+35.452797 471.64243 35.072264 471.54217 34.703125 471.40546 curveto
+34.703125 470.18182 lineto
+35.072264 470.38234 35.436847 470.53045 35.796875 470.62616 curveto
+36.156898 470.72186 36.52376 470.76971 36.897461 470.76971 curveto
+37.722326 470.76971 38.339838 470.55324 38.75 470.1203 curveto
+39.16015 469.69191 39.365228 469.0425 39.365234 468.17206 curveto
+39.365234 467.54999 lineto
+39.105463 468.00116 38.772781 468.3384 38.367188 468.56171 curveto
+37.961584 468.78501 37.476233 468.89667 36.911133 468.89667 curveto
+35.972328 468.89667 35.215818 468.53892 34.641602 467.82343 curveto
+34.067382 467.10793 33.780273 466.16002 33.780273 464.97968 curveto
+33.780273 463.79478 34.067382 462.84459 34.641602 462.12909 curveto
+35.215818 461.4136 35.972328 461.05586 36.911133 461.05585 curveto
+37.476233 461.05586 37.961584 461.16751 38.367188 461.39081 curveto
+38.772781 461.61412 39.105463 461.95136 39.365234 462.40253 curveto
+39.365234 461.24042 lineto
+40.623047 461.24042 lineto
+40.623047 467.94647 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+43.015625 458.27362 moveto
+44.109375 458.27362 lineto
+44.792966 459.34915 45.303382 460.40188 45.640625 461.43182 curveto
+45.982418 462.46178 46.153316 463.48489 46.15332 464.50116 curveto
+46.153316 465.522 45.982418 466.54966 45.640625 467.58417 curveto
+45.303382 468.61867 44.792966 469.67141 44.109375 470.74237 curveto
+43.015625 470.74237 lineto
+43.621743 469.69875 44.072914 468.66197 44.369141 467.63202 curveto
+44.669919 466.59752 44.82031 465.5539 44.820312 464.50116 curveto
+44.82031 463.44843 44.669919 462.40937 44.369141 461.38397 curveto
+44.072914 460.35859 43.621743 459.32181 43.015625 458.27362 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+98.233398 458.80682 moveto
+97.622718 459.85501 97.169268 460.89179 96.873047 461.91718 curveto
+96.57682 462.94257 96.428708 463.98163 96.428711 465.03436 curveto
+96.428708 466.0871 96.57682 467.13072 96.873047 468.16522 curveto
+97.173825 469.19517 97.627275 470.23195 98.233398 471.27557 curveto
+97.139648 471.27557 lineto
+96.456052 470.20461 95.943357 469.15188 95.601562 468.11737 curveto
+95.264322 467.08287 95.095702 466.0552 95.095703 465.03436 curveto
+95.095702 464.01809 95.264322 462.99498 95.601562 461.96503 curveto
+95.9388 460.93509 96.451495 459.88235 97.139648 458.80682 curveto
+98.233398 458.80682 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+103.98242 463.77655 moveto
+103.36263 463.77656 102.87044 463.98847 102.50586 464.41229 curveto
+102.14583 464.83613 101.96582 465.41718 101.96582 466.15546 curveto
+101.96582 466.88918 102.14583 467.47024 102.50586 467.89862 curveto
+102.87044 468.32245 103.36263 468.53436 103.98242 468.53436 curveto
+104.60221 468.53436 105.09212 468.32245 105.45215 467.89862 curveto
+105.81673 467.47024 105.99902 466.88918 105.99902 466.15546 curveto
+105.99902 465.41718 105.81673 464.83613 105.45215 464.41229 curveto
+105.09212 463.98847 104.60221 463.77656 103.98242 463.77655 curveto
+106.72363 459.4494 moveto
+106.72363 460.70721 lineto
+106.37727 460.54316 106.02636 460.41784 105.6709 460.33124 curveto
+105.31998 460.24466 104.97135 460.20136 104.625 460.20135 curveto
+103.71354 460.20136 103.01627 460.50898 102.5332 461.12421 curveto
+102.05468 461.73945 101.78125 462.66914 101.71289 463.91327 curveto
+101.98177 463.51679 102.31901 463.21373 102.72461 463.00409 curveto
+103.1302 462.7899 103.57682 462.68281 104.06445 462.6828 curveto
+105.08984 462.68281 105.89876 462.99498 106.49121 463.61932 curveto
+107.08821 464.23912 107.38671 465.0845 107.38672 466.15546 curveto
+107.38671 467.20364 107.07682 468.04446 106.45703 468.67792 curveto
+105.83723 469.31138 105.01236 469.62811 103.98242 469.62811 curveto
+102.80208 469.62811 101.89974 469.17694 101.27539 468.2746 curveto
+100.65104 467.3677 100.33887 466.0552 100.33887 464.3371 curveto
+100.33887 462.72382 100.72168 461.43867 101.4873 460.48163 curveto
+102.25293 459.52005 103.2806 459.03926 104.57031 459.03925 curveto
+104.91666 459.03926 105.26529 459.07344 105.61621 459.14178 curveto
+105.97167 459.21015 106.34081 459.31269 106.72363 459.4494 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+109.91602 467.69354 moveto
+111.3584 467.69354 lineto
+111.3584 468.86932 lineto
+110.2373 471.05682 lineto
+109.35547 471.05682 lineto
+109.91602 468.86932 lineto
+109.91602 467.69354 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+114.24316 459.22382 moveto
+119.66406 459.22382 lineto
+119.66406 460.38593 lineto
+115.50781 460.38593 lineto
+115.50781 462.88788 lineto
+115.70833 462.81953 115.90885 462.7694 116.10938 462.73749 curveto
+116.30989 462.70104 116.51041 462.68281 116.71094 462.6828 curveto
+117.85026 462.68281 118.7526 462.99498 119.41797 463.61932 curveto
+120.08333 464.24368 120.41601 465.08905 120.41602 466.15546 curveto
+120.41601 467.25377 120.07421 468.10826 119.39062 468.71893 curveto
+118.70703 469.32505 117.74316 469.62811 116.49902 469.62811 curveto
+116.07063 469.62811 115.63314 469.59165 115.18652 469.51874 curveto
+114.74446 469.44582 114.28646 469.33645 113.8125 469.19061 curveto
+113.8125 467.80292 lineto
+114.22265 468.02623 114.64648 468.19257 115.08398 468.30194 curveto
+115.52148 468.41132 115.98405 468.466 116.47168 468.466 curveto
+117.26009 468.466 117.88443 468.25865 118.34473 467.84393 curveto
+118.80501 467.42922 119.03515 466.8664 119.03516 466.15546 curveto
+119.03515 465.44452 118.80501 464.8817 118.34473 464.46698 curveto
+117.88443 464.05227 117.26009 463.84492 116.47168 463.84491 curveto
+116.10254 463.84492 115.7334 463.88593 115.36426 463.96796 curveto
+114.99967 464.04999 114.62597 464.1776 114.24316 464.35077 curveto
+114.24316 459.22382 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+123.28711 467.69354 moveto
+124.72949 467.69354 lineto
+124.72949 468.86932 lineto
+123.6084 471.05682 lineto
+122.72656 471.05682 lineto
+123.28711 468.86932 lineto
+123.28711 467.69354 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+130.38965 462.65546 moveto
+129.71517 462.65546 129.18196 462.91979 128.79004 463.44843 curveto
+128.39811 463.97252 128.20215 464.69257 128.20215 465.60858 curveto
+128.20215 466.5246 128.39583 467.24693 128.7832 467.77557 curveto
+129.17513 468.29966 129.71061 468.56171 130.38965 468.56171 curveto
+131.05957 468.56171 131.59049 468.29738 131.98242 467.76874 curveto
+132.37434 467.24009 132.57031 466.52004 132.57031 465.60858 curveto
+132.57031 464.70169 132.37434 463.98391 131.98242 463.45526 curveto
+131.59049 462.92206 131.05957 462.65546 130.38965 462.65546 curveto
+130.38965 461.58905 moveto
+131.48339 461.58906 132.34244 461.94453 132.9668 462.65546 curveto
+133.59114 463.3664 133.90331 464.35077 133.90332 465.60858 curveto
+133.90331 466.86184 133.59114 467.84621 132.9668 468.56171 curveto
+132.34244 469.27264 131.48339 469.62811 130.38965 469.62811 curveto
+129.29134 469.62811 128.43001 469.27264 127.80566 468.56171 curveto
+127.18587 467.84621 126.87598 466.86184 126.87598 465.60858 curveto
+126.87598 464.35077 127.18587 463.3664 127.80566 462.65546 curveto
+128.43001 461.94453 129.29134 461.58906 130.38965 461.58905 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+135.7832 458.80682 moveto
+136.87695 458.80682 lineto
+137.56054 459.88235 138.07096 460.93509 138.4082 461.96503 curveto
+138.75 462.99498 138.92089 464.01809 138.9209 465.03436 curveto
+138.92089 466.0552 138.75 467.08287 138.4082 468.11737 curveto
+138.07096 469.15188 137.56054 470.20461 136.87695 471.27557 curveto
+135.7832 471.27557 lineto
+136.38932 470.23195 136.84049 469.19517 137.13672 468.16522 curveto
+137.4375 467.13072 137.58789 466.0871 137.58789 465.03436 curveto
+137.58789 463.98163 137.4375 462.94257 137.13672 461.91718 curveto
+136.84049 460.89179 136.38932 459.85501 135.7832 458.80682 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+4.1689453 477.84198 moveto
+3.5582645 478.89017 3.1048144 479.92695 2.8085938 480.95233 curveto
+2.5123671 481.97773 2.3642553 483.01679 2.3642578 484.06952 curveto
+2.3642553 485.12226 2.5123671 486.16588 2.8085938 487.20038 curveto
+3.1093717 488.23033 3.5628218 489.26711 4.1689453 490.31073 curveto
+3.0751953 490.31073 lineto
+2.391599 489.23977 1.8789042 488.18703 1.5371094 487.15253 curveto
+1.1998684 486.11802 1.0312488 485.09036 1.03125 484.06952 curveto
+1.0312488 483.05325 1.1998684 482.03014 1.5371094 481.00018 curveto
+1.8743469 479.97024 2.3870417 478.91751 3.0751953 477.84198 curveto
+4.1689453 477.84198 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+6.4453125 478.25897 moveto
+13.007812 478.25897 lineto
+13.007812 478.84686 lineto
+9.3027344 488.46503 lineto
+7.8603516 488.46503 lineto
+11.34668 479.42108 lineto
+6.4453125 479.42108 lineto
+6.4453125 478.25897 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+15.851562 486.7287 moveto
+17.293945 486.7287 lineto
+17.293945 487.90448 lineto
+16.172852 490.09198 lineto
+15.291016 490.09198 lineto
+15.851562 487.90448 lineto
+15.851562 486.7287 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+23.289062 482.81171 moveto
+22.669267 482.81171 22.17708 483.02363 21.8125 483.44745 curveto
+21.452471 483.87128 21.272458 484.45234 21.272461 485.19061 curveto
+21.272458 485.92434 21.452471 486.50539 21.8125 486.93378 curveto
+22.17708 487.35761 22.669267 487.56952 23.289062 487.56952 curveto
+23.908849 487.56952 24.398757 487.35761 24.758789 486.93378 curveto
+25.123366 486.50539 25.305657 485.92434 25.305664 485.19061 curveto
+25.305657 484.45234 25.123366 483.87128 24.758789 483.44745 curveto
+24.398757 483.02363 23.908849 482.81171 23.289062 482.81171 curveto
+26.030273 478.48456 moveto
+26.030273 479.74237 lineto
+25.683912 479.57832 25.333001 479.45299 24.977539 479.36639 curveto
+24.626622 479.27981 24.277989 479.23652 23.931641 479.23651 curveto
+23.020178 479.23652 22.322913 479.54414 21.839844 480.15936 curveto
+21.361325 480.7746 21.087888 481.70429 21.019531 482.94843 curveto
+21.288409 482.55195 21.625648 482.24889 22.03125 482.03925 curveto
+22.436845 481.82506 22.883459 481.71796 23.371094 481.71796 curveto
+24.396479 481.71796 25.205397 482.03014 25.797852 482.65448 curveto
+26.394849 483.27428 26.693351 484.11965 26.693359 485.19061 curveto
+26.693351 486.23879 26.383456 487.07961 25.763672 487.71307 curveto
+25.143874 488.34654 24.319005 488.66327 23.289062 488.66327 curveto
+22.108721 488.66327 21.206378 488.2121 20.582031 487.30975 curveto
+19.957681 486.40285 19.645507 485.09036 19.645508 483.37225 curveto
+19.645507 481.75898 20.028319 480.47382 20.793945 479.51678 curveto
+21.559567 478.55521 22.587236 478.07441 23.876953 478.0744 curveto
+24.223302 478.07441 24.571934 478.10859 24.922852 478.17694 curveto
+25.278314 478.24531 25.647454 478.34785 26.030273 478.48456 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+29.222656 486.7287 moveto
+30.665039 486.7287 lineto
+30.665039 487.90448 lineto
+29.543945 490.09198 lineto
+28.662109 490.09198 lineto
+29.222656 487.90448 lineto
+29.222656 486.7287 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+36.325195 481.69061 moveto
+35.650713 481.69062 35.11751 481.95494 34.725586 482.48358 curveto
+34.333657 483.00768 34.137693 483.72773 34.137695 484.64374 curveto
+34.137693 485.55976 34.331378 486.28209 34.71875 486.81073 curveto
+35.110674 487.33482 35.646155 487.59686 36.325195 487.59686 curveto
+36.995112 487.59686 37.526036 487.33254 37.917969 486.80389 curveto
+38.30989 486.27525 38.505853 485.5552 38.505859 484.64374 curveto
+38.505853 483.73684 38.30989 483.01907 37.917969 482.49042 curveto
+37.526036 481.95722 36.995112 481.69062 36.325195 481.69061 curveto
+36.325195 480.62421 moveto
+37.41894 480.62421 38.277989 480.97968 38.902344 481.69061 curveto
+39.526685 482.40156 39.838859 483.38593 39.838867 484.64374 curveto
+39.838859 485.897 39.526685 486.88137 38.902344 487.59686 curveto
+38.277989 488.3078 37.41894 488.66327 36.325195 488.66327 curveto
+35.226885 488.66327 34.365558 488.3078 33.741211 487.59686 curveto
+33.121418 486.88137 32.811523 485.897 32.811523 484.64374 curveto
+32.811523 483.38593 33.121418 482.40156 33.741211 481.69061 curveto
+34.365558 480.97968 35.226885 480.62421 36.325195 480.62421 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+41.71875 477.84198 moveto
+42.8125 477.84198 lineto
+43.496091 478.91751 44.006507 479.97024 44.34375 481.00018 curveto
+44.685543 482.03014 44.856441 483.05325 44.856445 484.06952 curveto
+44.856441 485.09036 44.685543 486.11802 44.34375 487.15253 curveto
+44.006507 488.18703 43.496091 489.23977 42.8125 490.31073 curveto
+41.71875 490.31073 lineto
+42.324868 489.26711 42.776039 488.23033 43.072266 487.20038 curveto
+43.373044 486.16588 43.523435 485.12226 43.523438 484.06952 curveto
+43.523435 483.01679 43.373044 481.97773 43.072266 480.95233 curveto
+42.776039 479.92695 42.324868 478.89017 41.71875 477.84198 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+51.951172 478.34198 moveto
+51.340491 479.39017 50.887041 480.42695 50.59082 481.45233 curveto
+50.294594 482.47773 50.146482 483.51679 50.146484 484.56952 curveto
+50.146482 485.62226 50.294594 486.66588 50.59082 487.70038 curveto
+50.891598 488.73033 51.345048 489.76711 51.951172 490.81073 curveto
+50.857422 490.81073 lineto
+50.173826 489.73977 49.661131 488.68703 49.319336 487.65253 curveto
+48.982095 486.61802 48.813475 485.59036 48.813477 484.56952 curveto
+48.813475 483.55325 48.982095 482.53014 49.319336 481.50018 curveto
+49.656573 480.47024 50.169268 479.41751 50.857422 478.34198 curveto
+51.951172 478.34198 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+57.529297 484.11835 moveto
+56.873043 484.11835 56.355791 484.29381 55.977539 484.64471 curveto
+55.603839 484.99563 55.41699 485.4787 55.416992 486.09393 curveto
+55.41699 486.70917 55.603839 487.19224 55.977539 487.54315 curveto
+56.355791 487.89406 56.873043 488.06952 57.529297 488.06952 curveto
+58.185542 488.06952 58.702794 487.89406 59.081055 487.54315 curveto
+59.459304 487.18768 59.648431 486.70461 59.648438 486.09393 curveto
+59.648431 485.4787 59.459304 484.99563 59.081055 484.64471 curveto
+58.707351 484.29381 58.190099 484.11835 57.529297 484.11835 curveto
+56.148438 483.53046 moveto
+55.555987 483.38463 55.093422 483.10891 54.760742 482.70331 curveto
+54.432616 482.29772 54.268553 481.80325 54.268555 481.21991 curveto
+54.268553 480.40416 54.557941 479.75931 55.136719 479.28534 curveto
+55.720049 478.81139 56.517575 478.57441 57.529297 478.5744 curveto
+58.545567 478.57441 59.343093 478.81139 59.921875 479.28534 curveto
+60.500644 479.75931 60.790031 480.40416 60.790039 481.21991 curveto
+60.790031 481.80325 60.62369 482.29772 60.291016 482.70331 curveto
+59.962884 483.10891 59.504876 483.38463 58.916992 483.53046 curveto
+59.58235 483.68541 60.099602 483.98847 60.46875 484.43964 curveto
+60.84244 484.89081 61.029289 485.44224 61.029297 486.09393 curveto
+61.029289 487.08287 60.726229 487.84166 60.120117 488.3703 curveto
+59.518548 488.89895 58.654942 489.16327 57.529297 489.16327 curveto
+56.403643 489.16327 55.537758 488.89895 54.931641 488.3703 curveto
+54.330077 487.84166 54.029296 487.08287 54.029297 486.09393 curveto
+54.029296 485.44224 54.216145 484.89081 54.589844 484.43964 curveto
+54.96354 483.98847 55.483071 483.68541 56.148438 483.53046 curveto
+55.642578 481.34979 moveto
+55.642576 481.87845 55.806638 482.29088 56.134766 482.5871 curveto
+56.467445 482.88333 56.932288 483.03144 57.529297 483.03143 curveto
+58.12174 483.03144 58.584304 482.88333 58.916992 482.5871 curveto
+59.254226 482.29088 59.422845 481.87845 59.422852 481.34979 curveto
+59.422845 480.82115 59.254226 480.40872 58.916992 480.11249 curveto
+58.584304 479.81627 58.12174 479.66816 57.529297 479.66815 curveto
+56.932288 479.66816 56.467445 479.81627 56.134766 480.11249 curveto
+55.806638 480.40872 55.642576 480.82115 55.642578 481.34979 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+63.633789 487.2287 moveto
+65.076172 487.2287 lineto
+65.076172 488.40448 lineto
+63.955078 490.59198 lineto
+63.073242 490.59198 lineto
+63.633789 488.40448 lineto
+63.633789 487.2287 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+67.598633 478.75897 moveto
+74.161133 478.75897 lineto
+74.161133 479.34686 lineto
+70.456055 488.96503 lineto
+69.013672 488.96503 lineto
+72.5 479.92108 lineto
+67.598633 479.92108 lineto
+67.598633 478.75897 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+77.004883 487.2287 moveto
+78.447266 487.2287 lineto
+78.447266 488.40448 lineto
+77.326172 490.59198 lineto
+76.444336 490.59198 lineto
+77.004883 488.40448 lineto
+77.004883 487.2287 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+84.107422 482.19061 moveto
+83.432939 482.19062 82.899737 482.45494 82.507812 482.98358 curveto
+82.115883 483.50768 81.91992 484.22773 81.919922 485.14374 curveto
+81.91992 486.05976 82.113604 486.78209 82.500977 487.31073 curveto
+82.892901 487.83482 83.428382 488.09686 84.107422 488.09686 curveto
+84.777339 488.09686 85.308263 487.83254 85.700195 487.30389 curveto
+86.092116 486.77525 86.288079 486.0552 86.288086 485.14374 curveto
+86.288079 484.23684 86.092116 483.51907 85.700195 482.99042 curveto
+85.308263 482.45722 84.777339 482.19062 84.107422 482.19061 curveto
+84.107422 481.12421 moveto
+85.201166 481.12421 86.060215 481.47968 86.68457 482.19061 curveto
+87.308912 482.90156 87.621086 483.88593 87.621094 485.14374 curveto
+87.621086 486.397 87.308912 487.38137 86.68457 488.09686 curveto
+86.060215 488.8078 85.201166 489.16327 84.107422 489.16327 curveto
+83.009111 489.16327 82.147784 488.8078 81.523438 488.09686 curveto
+80.903645 487.38137 80.593749 486.397 80.59375 485.14374 curveto
+80.593749 483.88593 80.903645 482.90156 81.523438 482.19061 curveto
+82.147784 481.47968 83.009111 481.12421 84.107422 481.12421 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+89.500977 478.34198 moveto
+90.594727 478.34198 lineto
+91.278317 479.41751 91.788734 480.47024 92.125977 481.50018 curveto
+92.467769 482.53014 92.638668 483.55325 92.638672 484.56952 curveto
+92.638668 485.59036 92.467769 486.61802 92.125977 487.65253 curveto
+91.788734 488.68703 91.278317 489.73977 90.594727 490.81073 curveto
+89.500977 490.81073 lineto
+90.107095 489.76711 90.558266 488.73033 90.854492 487.70038 curveto
+91.155271 486.66588 91.305661 485.62226 91.305664 484.56952 curveto
+91.305661 483.51679 91.155271 482.47773 90.854492 481.45233 curveto
+90.558266 480.42695 90.107095 479.39017 89.500977 478.34198 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+96.905273 479.30878 moveto
+96.294593 480.35696 95.841143 481.39375 95.544922 482.41913 curveto
+95.248695 483.44453 95.100583 484.48359 95.100586 485.53632 curveto
+95.100583 486.58905 95.248695 487.63267 95.544922 488.66718 curveto
+95.8457 489.69712 96.29915 490.73391 96.905273 491.77753 curveto
+95.811523 491.77753 lineto
+95.127927 490.70656 94.615232 489.65383 94.273438 488.61932 curveto
+93.936197 487.58482 93.767577 486.55715 93.767578 485.53632 curveto
+93.767577 484.52005 93.936197 483.49693 94.273438 482.46698 curveto
+94.610675 481.43704 95.12337 480.38431 95.811523 479.30878 curveto
+96.905273 479.30878 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+99.571289 489.71991 moveto
+99.571289 488.4621 lineto
+99.917641 488.62616 100.26855 488.75149 100.62402 488.83807 curveto
+100.97949 488.92466 101.32812 488.96796 101.66992 488.96796 curveto
+102.58138 488.96796 103.27636 488.66262 103.75488 488.05194 curveto
+104.23795 487.43671 104.51367 486.50474 104.58203 485.25604 curveto
+104.3177 485.64797 103.98274 485.94875 103.57715 486.15839 curveto
+103.17154 486.36803 102.72265 486.47284 102.23047 486.47284 curveto
+101.20963 486.47284 100.40071 486.16523 99.803711 485.54999 curveto
+99.211262 484.9302 98.915038 484.08482 98.915039 483.01385 curveto
+98.915038 481.96569 99.224934 481.12487 99.844727 480.49139 curveto
+100.46452 479.85794 101.28938 479.54121 102.31934 479.5412 curveto
+103.49967 479.54121 104.39973 479.99466 105.01953 480.90155 curveto
+105.64387 481.8039 105.95605 483.1164 105.95605 484.83905 curveto
+105.95605 486.44778 105.57323 487.73293 104.80762 488.69452 curveto
+104.04654 489.65155 103.02115 490.13007 101.73145 490.13007 curveto
+101.38509 490.13007 101.03418 490.09589 100.67871 490.02753 curveto
+100.32324 489.95917 99.9541 489.85663 99.571289 489.71991 curveto
+102.31934 485.39276 moveto
+102.93912 485.39277 103.42903 485.18085 103.78906 484.75702 curveto
+104.15364 484.3332 104.33593 483.75214 104.33594 483.01385 curveto
+104.33593 482.28014 104.15364 481.70136 103.78906 481.27753 curveto
+103.42903 480.84915 102.93912 480.63496 102.31934 480.63495 curveto
+101.69954 480.63496 101.20735 480.84915 100.84277 481.27753 curveto
+100.48274 481.70136 100.30273 482.28014 100.30273 483.01385 curveto
+100.30273 483.75214 100.48274 484.3332 100.84277 484.75702 curveto
+101.20735 485.18085 101.69954 485.39277 102.31934 485.39276 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+108.58789 488.1955 moveto
+110.03027 488.1955 lineto
+110.03027 489.37128 lineto
+108.90918 491.55878 lineto
+108.02734 491.55878 lineto
+108.58789 489.37128 lineto
+108.58789 488.1955 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+115.85449 485.08514 moveto
+115.19824 485.08515 114.68099 485.2606 114.30273 485.61151 curveto
+113.92903 485.96243 113.74219 486.4455 113.74219 487.06073 curveto
+113.74219 487.67597 113.92903 488.15904 114.30273 488.50995 curveto
+114.68099 488.86086 115.19824 489.03632 115.85449 489.03632 curveto
+116.51074 489.03632 117.02799 488.86086 117.40625 488.50995 curveto
+117.7845 488.15448 117.97363 487.67141 117.97363 487.06073 curveto
+117.97363 486.4455 117.7845 485.96243 117.40625 485.61151 curveto
+117.03255 485.2606 116.51529 485.08515 115.85449 485.08514 curveto
+114.47363 484.49725 moveto
+113.88118 484.35143 113.41862 484.07571 113.08594 483.6701 curveto
+112.75781 483.26451 112.59375 482.77005 112.59375 482.18671 curveto
+112.59375 481.37096 112.88314 480.7261 113.46191 480.25214 curveto
+114.04524 479.77819 114.84277 479.54121 115.85449 479.5412 curveto
+116.87076 479.54121 117.66829 479.77819 118.24707 480.25214 curveto
+118.82584 480.7261 119.11523 481.37096 119.11523 482.18671 curveto
+119.11523 482.77005 118.94889 483.26451 118.61621 483.6701 curveto
+118.28808 484.07571 117.83007 484.35143 117.24219 484.49725 curveto
+117.90755 484.65221 118.4248 484.95527 118.79395 485.40643 curveto
+119.16764 485.85761 119.35448 486.40904 119.35449 487.06073 curveto
+119.35448 488.04966 119.05142 488.80845 118.44531 489.3371 curveto
+117.84374 489.86574 116.98014 490.13007 115.85449 490.13007 curveto
+114.72884 490.13007 113.86295 489.86574 113.25684 489.3371 curveto
+112.65527 488.80845 112.35449 488.04966 112.35449 487.06073 curveto
+112.35449 486.40904 112.54134 485.85761 112.91504 485.40643 curveto
+113.28874 484.95527 113.80827 484.65221 114.47363 484.49725 curveto
+113.96777 482.31659 moveto
+113.96777 482.84524 114.13183 483.25768 114.45996 483.55389 curveto
+114.79264 483.85012 115.25748 483.99824 115.85449 483.99823 curveto
+116.44694 483.99824 116.9095 483.85012 117.24219 483.55389 curveto
+117.57942 483.25768 117.74804 482.84524 117.74805 482.31659 curveto
+117.74804 481.78795 117.57942 481.37552 117.24219 481.07928 curveto
+116.9095 480.78307 116.44694 480.63496 115.85449 480.63495 curveto
+115.25748 480.63496 114.79264 480.78307 114.45996 481.07928 curveto
+114.13183 481.37552 113.96777 481.78795 113.96777 482.31659 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+121.95898 488.1955 moveto
+123.40137 488.1955 lineto
+123.40137 489.37128 lineto
+122.28027 491.55878 lineto
+121.39844 491.55878 lineto
+121.95898 489.37128 lineto
+121.95898 488.1955 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+131.13281 486.01483 moveto
+131.13281 485.10338 130.94368 484.397 130.56543 483.89569 curveto
+130.19173 483.3944 129.66536 483.14374 128.98633 483.14374 curveto
+128.31185 483.14374 127.78548 483.3944 127.40723 483.89569 curveto
+127.03353 484.397 126.84668 485.10338 126.84668 486.01483 curveto
+126.84668 486.92174 127.03353 487.62584 127.40723 488.12714 curveto
+127.78548 488.62844 128.31185 488.87909 128.98633 488.87909 curveto
+129.66536 488.87909 130.19173 488.62844 130.56543 488.12714 curveto
+130.94368 487.62584 131.13281 486.92174 131.13281 486.01483 curveto
+132.39062 488.98163 moveto
+132.39062 490.28501 132.10123 491.25344 131.52246 491.8869 curveto
+130.94368 492.52492 130.05729 492.84393 128.86328 492.84393 curveto
+128.42122 492.84393 128.00423 492.80975 127.6123 492.74139 curveto
+127.22038 492.67759 126.83984 492.57733 126.4707 492.44061 curveto
+126.4707 491.21698 lineto
+126.83984 491.4175 127.20442 491.56561 127.56445 491.66132 curveto
+127.92448 491.75702 128.29134 491.80487 128.66504 491.80487 curveto
+129.4899 491.80487 130.10742 491.5884 130.51758 491.15546 curveto
+130.92773 490.72707 131.13281 490.07766 131.13281 489.20721 curveto
+131.13281 488.58514 lineto
+130.87304 489.03632 130.54036 489.37356 130.13477 489.59686 curveto
+129.72916 489.82017 129.24381 489.93182 128.67871 489.93182 curveto
+127.73991 489.93182 126.9834 489.57408 126.40918 488.85858 curveto
+125.83496 488.14309 125.54785 487.19517 125.54785 486.01483 curveto
+125.54785 484.82994 125.83496 483.87975 126.40918 483.16425 curveto
+126.9834 482.44876 127.73991 482.09101 128.67871 482.091 curveto
+129.24381 482.09101 129.72916 482.20266 130.13477 482.42596 curveto
+130.54036 482.64928 130.87304 482.98652 131.13281 483.43768 curveto
+131.13281 482.27557 lineto
+132.39062 482.27557 lineto
+132.39062 488.98163 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+134.7832 479.30878 moveto
+135.87695 479.30878 lineto
+136.56054 480.38431 137.07096 481.43704 137.4082 482.46698 curveto
+137.75 483.49693 137.92089 484.52005 137.9209 485.53632 curveto
+137.92089 486.55715 137.75 487.58482 137.4082 488.61932 curveto
+137.07096 489.65383 136.56054 490.70656 135.87695 491.77753 curveto
+134.7832 491.77753 lineto
+135.38932 490.73391 135.84049 489.69712 136.13672 488.66718 curveto
+136.4375 487.63267 136.58789 486.58905 136.58789 485.53632 curveto
+136.58789 484.48359 136.4375 483.44453 136.13672 482.41913 curveto
+135.84049 481.39375 135.38932 480.35696 134.7832 479.30878 curveto
+fill
+grestore
+gsave [1.209899 0 0 0.857509 -38.19343 49.51799] concat
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+154.5 482.61218 moveto
+154.5 515.59418 125.716 542.36218 90.25 542.36218 curveto
+54.784 542.36218 26 515.59418 26 482.61218 curveto
+26 449.63018 54.784 422.86218 90.25 422.86218 curveto
+125.716 422.86218 154.5 449.63018 154.5 482.61218 curveto
+closepath
+stroke
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+67.874023 420.15613 moveto
+69.254883 420.15613 lineto
+69.254883 430.36218 lineto
+67.874023 430.36218 lineto
+67.874023 420.15613 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+73.192383 420.5321 moveto
+73.192383 422.70593 lineto
+75.783203 422.70593 lineto
+75.783203 423.68347 lineto
+73.192383 423.68347 lineto
+73.192383 427.83972 lineto
+73.19238 428.46407 73.27669 428.86511 73.445312 429.04285 curveto
+73.618487 429.22058 73.967119 429.30945 74.491211 429.30945 curveto
+75.783203 429.30945 lineto
+75.783203 430.36218 lineto
+74.491211 430.36218 lineto
+73.520505 430.36218 72.850584 430.18217 72.481445 429.82214 curveto
+72.112303 429.45756 71.927733 428.79675 71.927734 427.83972 curveto
+71.927734 423.68347 lineto
+71.004883 423.68347 lineto
+71.004883 422.70593 lineto
+71.927734 422.70593 lineto
+71.927734 420.5321 lineto
+73.192383 420.5321 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+59.254883 524.79089 moveto
+59.254883 528.62585 lineto
+60.991211 528.62585 lineto
+61.633784 528.62586 62.130528 528.45952 62.481445 528.12683 curveto
+62.83235 527.79415 63.007806 527.3202 63.007812 526.70496 curveto
+63.007806 526.09429 62.83235 525.62261 62.481445 525.28992 curveto
+62.130528 524.95724 61.633784 524.7909 60.991211 524.79089 curveto
+59.254883 524.79089 lineto
+57.874023 523.65613 moveto
+60.991211 523.65613 lineto
+62.135086 523.65614 62.998691 523.9159 63.582031 524.43542 curveto
+64.169914 524.95041 64.463859 525.70692 64.463867 526.70496 curveto
+64.463859 527.71212 64.169914 528.47319 63.582031 528.98816 curveto
+62.998691 529.50314 62.135086 529.76062 60.991211 529.76062 curveto
+59.254883 529.76062 lineto
+59.254883 533.86218 lineto
+57.874023 533.86218 lineto
+57.874023 523.65613 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+69.399414 524.56531 moveto
+68.688473 524.56532 68.152992 524.91623 67.792969 525.61804 curveto
+67.437498 526.31532 67.259763 527.36577 67.259766 528.76941 curveto
+67.259763 530.1685 67.437498 531.21896 67.792969 531.92078 curveto
+68.152992 532.61804 68.688473 532.96668 69.399414 532.96667 curveto
+70.114904 532.96668 70.650385 532.61804 71.005859 531.92078 curveto
+71.365879 531.21896 71.545892 530.1685 71.545898 528.76941 curveto
+71.545892 527.36577 71.365879 526.31532 71.005859 525.61804 curveto
+70.650385 524.91623 70.114904 524.56532 69.399414 524.56531 curveto
+69.399414 523.47156 moveto
+70.543289 523.47157 71.416009 523.92502 72.017578 524.83191 curveto
+72.62369 525.73426 72.92675 527.04676 72.926758 528.76941 curveto
+72.92675 530.48751 72.62369 531.80001 72.017578 532.70691 curveto
+71.416009 533.60925 70.543289 534.06042 69.399414 534.06042 curveto
+68.255531 534.06042 67.380531 533.60925 66.774414 532.70691 curveto
+66.17285 531.80001 65.872069 530.48751 65.87207 528.76941 curveto
+65.872069 527.04676 66.17285 525.73426 66.774414 524.83191 curveto
+67.380531 523.92502 68.255531 523.47157 69.399414 523.47156 curveto
+fill
+grestore
+gsave [1.063088 0 0 0.999533 -49.82231 5.914079] concat
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+349.5 351.36218 moveto
+349.5 378.68618 319.484 400.86218 282.5 400.86218 curveto
+245.516 400.86218 215.5 378.68618 215.5 351.36218 curveto
+215.5 324.03818 245.516 301.86218 282.5 301.86218 curveto
+319.484 301.86218 349.5 324.03818 349.5 351.36218 curveto
+closepath
+stroke
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+205.85547 329.61218 moveto
+205.24479 330.66037 204.79134 331.69715 204.49512 332.72253 curveto
+204.19889 333.74793 204.05078 334.78699 204.05078 335.83972 curveto
+204.05078 336.89246 204.19889 337.93608 204.49512 338.97058 curveto
+204.7959 340.00053 205.24935 341.03731 205.85547 342.08093 curveto
+204.76172 342.08093 lineto
+204.07812 341.00997 203.56543 339.95723 203.22363 338.92273 curveto
+202.88639 337.88823 202.71777 336.86056 202.71777 335.83972 curveto
+202.71777 334.82345 202.88639 333.80034 203.22363 332.77039 curveto
+203.56087 331.74045 204.07357 330.68771 204.76172 329.61218 curveto
+205.85547 329.61218 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+208.49414 330.02917 moveto
+213.91504 330.02917 lineto
+213.91504 331.19128 lineto
+209.75879 331.19128 lineto
+209.75879 333.69324 lineto
+209.95931 333.62488 210.15983 333.57475 210.36035 333.54285 curveto
+210.56087 333.5064 210.76139 333.48817 210.96191 333.48816 curveto
+212.10123 333.48817 213.00357 333.80034 213.66895 334.42468 curveto
+214.3343 335.04904 214.66698 335.89441 214.66699 336.96082 curveto
+214.66698 338.05912 214.32519 338.91362 213.6416 339.52429 curveto
+212.958 340.13041 211.99414 340.43347 210.75 340.43347 curveto
+210.32161 340.43347 209.88411 340.39701 209.4375 340.3241 curveto
+208.99544 340.25118 208.53743 340.14181 208.06348 339.99597 curveto
+208.06348 338.60828 lineto
+208.47363 338.83159 208.89746 338.99793 209.33496 339.1073 curveto
+209.77246 339.21668 210.23502 339.27136 210.72266 339.27136 curveto
+211.51106 339.27136 212.13541 339.06401 212.5957 338.64929 curveto
+213.05598 338.23458 213.28613 337.67176 213.28613 336.96082 curveto
+213.28613 336.24988 213.05598 335.68706 212.5957 335.27234 curveto
+212.13541 334.85763 211.51106 334.65027 210.72266 334.65027 curveto
+210.35351 334.65027 209.98437 334.69129 209.61523 334.77332 curveto
+209.25065 334.85535 208.87695 334.98296 208.49414 335.15613 curveto
+208.49414 330.02917 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+217.53809 338.4989 moveto
+218.98047 338.4989 lineto
+218.98047 339.67468 lineto
+217.85938 341.86218 lineto
+216.97754 341.86218 lineto
+217.53809 339.67468 lineto
+217.53809 338.4989 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+224.80469 330.93835 moveto
+224.09375 330.93836 223.55827 331.28927 223.19824 331.99109 curveto
+222.84277 332.68836 222.66504 333.73882 222.66504 335.14246 curveto
+222.66504 336.54155 222.84277 337.592 223.19824 338.29382 curveto
+223.55827 338.99109 224.09375 339.33972 224.80469 339.33972 curveto
+225.52018 339.33972 226.05566 338.99109 226.41113 338.29382 curveto
+226.77115 337.592 226.95117 336.54155 226.95117 335.14246 curveto
+226.95117 333.73882 226.77115 332.68836 226.41113 331.99109 curveto
+226.05566 331.28927 225.52018 330.93836 224.80469 330.93835 curveto
+224.80469 329.8446 moveto
+225.94856 329.84461 226.82128 330.29806 227.42285 331.20496 curveto
+228.02896 332.10731 228.33202 333.41981 228.33203 335.14246 curveto
+228.33202 336.86056 228.02896 338.17306 227.42285 339.07996 curveto
+226.82128 339.9823 225.94856 340.43347 224.80469 340.43347 curveto
+223.6608 340.43347 222.7858 339.9823 222.17969 339.07996 curveto
+221.57812 338.17306 221.27734 336.86056 221.27734 335.14246 curveto
+221.27734 333.41981 221.57812 332.10731 222.17969 331.20496 curveto
+222.7858 330.29806 223.6608 329.84461 224.80469 329.8446 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+230.90918 338.4989 moveto
+232.35156 338.4989 lineto
+232.35156 339.67468 lineto
+231.23047 341.86218 lineto
+230.34863 341.86218 lineto
+230.90918 339.67468 lineto
+230.90918 338.4989 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+240.08301 336.31824 moveto
+240.083 335.40678 239.89387 334.7004 239.51562 334.1991 curveto
+239.14192 333.6978 238.61556 333.44715 237.93652 333.44714 curveto
+237.26204 333.44715 236.73567 333.6978 236.35742 334.1991 curveto
+235.98372 334.7004 235.79687 335.40678 235.79688 336.31824 curveto
+235.79687 337.22514 235.98372 337.92924 236.35742 338.43054 curveto
+236.73567 338.93185 237.26204 339.1825 237.93652 339.1825 curveto
+238.61556 339.1825 239.14192 338.93185 239.51562 338.43054 curveto
+239.89387 337.92924 240.083 337.22514 240.08301 336.31824 curveto
+241.34082 339.28503 moveto
+241.34081 340.58842 241.05142 341.55684 240.47266 342.19031 curveto
+239.89387 342.82833 239.00748 343.14734 237.81348 343.14734 curveto
+237.37142 343.14734 236.95442 343.11316 236.5625 343.0448 curveto
+236.17057 342.98099 235.79004 342.88073 235.4209 342.74402 curveto
+235.4209 341.52039 lineto
+235.79004 341.72091 236.15462 341.86902 236.51465 341.96472 curveto
+236.87467 342.06042 237.24153 342.10827 237.61523 342.10828 curveto
+238.4401 342.10827 239.05761 341.8918 239.46777 341.45886 curveto
+239.87792 341.03048 240.083 340.38106 240.08301 339.51062 curveto
+240.08301 338.88855 lineto
+239.82324 339.33972 239.49055 339.67696 239.08496 339.90027 curveto
+238.67936 340.12358 238.19401 340.23523 237.62891 340.23523 curveto
+236.6901 340.23523 235.93359 339.87748 235.35938 339.16199 curveto
+234.78516 338.44649 234.49805 337.49858 234.49805 336.31824 curveto
+234.49805 335.13335 234.78516 334.18315 235.35938 333.46765 curveto
+235.93359 332.75216 236.6901 332.39442 237.62891 332.39441 curveto
+238.19401 332.39442 238.67936 332.50607 239.08496 332.72937 curveto
+239.49055 332.95268 239.82324 333.28992 240.08301 333.74109 curveto
+240.08301 332.57898 lineto
+241.34082 332.57898 lineto
+241.34082 339.28503 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+243.7334 329.61218 moveto
+244.82715 329.61218 lineto
+245.51074 330.68771 246.02116 331.74045 246.3584 332.77039 curveto
+246.70019 333.80034 246.87109 334.82345 246.87109 335.83972 curveto
+246.87109 336.86056 246.70019 337.88823 246.3584 338.92273 curveto
+246.02116 339.95723 245.51074 341.00997 244.82715 342.08093 curveto
+243.7334 342.08093 lineto
+244.33952 341.03731 244.79069 340.00053 245.08691 338.97058 curveto
+245.38769 337.93608 245.53808 336.89246 245.53809 335.83972 curveto
+245.53808 334.78699 245.38769 333.74793 245.08691 332.72253 curveto
+244.79069 331.69715 244.33952 330.66037 243.7334 329.61218 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+253.34082 328.61218 moveto
+252.73014 329.66037 252.27669 330.69715 251.98047 331.72253 curveto
+251.68424 332.74793 251.53613 333.78699 251.53613 334.83972 curveto
+251.53613 335.89246 251.68424 336.93608 251.98047 337.97058 curveto
+252.28125 339.00053 252.7347 340.03731 253.34082 341.08093 curveto
+252.24707 341.08093 lineto
+251.56347 340.00997 251.05078 338.95723 250.70898 337.92273 curveto
+250.37174 336.88823 250.20312 335.86056 250.20312 334.83972 curveto
+250.20312 333.82345 250.37174 332.80034 250.70898 331.77039 curveto
+251.04622 330.74045 251.55892 329.68771 252.24707 328.61218 curveto
+253.34082 328.61218 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+259.08984 333.58191 moveto
+258.47005 333.58191 257.97786 333.79383 257.61328 334.21765 curveto
+257.25325 334.64148 257.07324 335.22254 257.07324 335.96082 curveto
+257.07324 336.69454 257.25325 337.2756 257.61328 337.70398 curveto
+257.97786 338.12781 258.47005 338.33972 259.08984 338.33972 curveto
+259.70963 338.33972 260.19954 338.12781 260.55957 337.70398 curveto
+260.92415 337.2756 261.10644 336.69454 261.10645 335.96082 curveto
+261.10644 335.22254 260.92415 334.64148 260.55957 334.21765 curveto
+260.19954 333.79383 259.70963 333.58191 259.08984 333.58191 curveto
+261.83105 329.25476 moveto
+261.83105 330.51257 lineto
+261.48469 330.34852 261.13378 330.22319 260.77832 330.1366 curveto
+260.4274 330.05002 260.07877 330.00672 259.73242 330.00671 curveto
+258.82096 330.00672 258.12369 330.31434 257.64062 330.92957 curveto
+257.16211 331.54481 256.88867 332.47449 256.82031 333.71863 curveto
+257.08919 333.32215 257.42643 333.01909 257.83203 332.80945 curveto
+258.23763 332.59526 258.68424 332.48817 259.17188 332.48816 curveto
+260.19726 332.48817 261.00618 332.80034 261.59863 333.42468 curveto
+262.19563 334.04448 262.49413 334.88986 262.49414 335.96082 curveto
+262.49413 337.00899 262.18424 337.84981 261.56445 338.48328 curveto
+260.94465 339.11674 260.11979 339.43347 259.08984 339.43347 curveto
+257.9095 339.43347 257.00716 338.9823 256.38281 338.07996 curveto
+255.75846 337.17306 255.44629 335.86056 255.44629 334.14246 curveto
+255.44629 332.52918 255.8291 331.24403 256.59473 330.28699 curveto
+257.36035 329.32541 258.38802 328.84461 259.67773 328.8446 curveto
+260.02408 328.84461 260.37272 328.87879 260.72363 328.94714 curveto
+261.07909 329.01551 261.44824 329.11805 261.83105 329.25476 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+265.02344 337.4989 moveto
+266.46582 337.4989 lineto
+266.46582 338.67468 lineto
+265.34473 340.86218 lineto
+264.46289 340.86218 lineto
+265.02344 338.67468 lineto
+265.02344 337.4989 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+269.57617 338.07312 moveto
+271.83203 338.07312 lineto
+271.83203 330.28699 lineto
+269.37793 330.77917 lineto
+269.37793 329.52136 lineto
+271.81836 329.02917 lineto
+273.19922 329.02917 lineto
+273.19922 338.07312 lineto
+275.45508 338.07312 lineto
+275.45508 339.23523 lineto
+269.57617 339.23523 lineto
+269.57617 338.07312 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+278.39453 337.4989 moveto
+279.83691 337.4989 lineto
+279.83691 338.67468 lineto
+278.71582 340.86218 lineto
+277.83398 340.86218 lineto
+278.39453 338.67468 lineto
+278.39453 337.4989 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+285.49707 332.46082 moveto
+284.82259 332.46082 284.28938 332.72514 283.89746 333.25378 curveto
+283.50553 333.77788 283.30957 334.49793 283.30957 335.41394 curveto
+283.30957 336.32996 283.50325 337.05229 283.89062 337.58093 curveto
+284.28255 338.10502 284.81803 338.36707 285.49707 338.36707 curveto
+286.16699 338.36707 286.69791 338.10274 287.08984 337.5741 curveto
+287.48176 337.04545 287.67773 336.3254 287.67773 335.41394 curveto
+287.67773 334.50704 287.48176 333.78927 287.08984 333.26062 curveto
+286.69791 332.72742 286.16699 332.46082 285.49707 332.46082 curveto
+285.49707 331.39441 moveto
+286.59081 331.39442 287.44986 331.74989 288.07422 332.46082 curveto
+288.69856 333.17176 289.01073 334.15613 289.01074 335.41394 curveto
+289.01073 336.6672 288.69856 337.65157 288.07422 338.36707 curveto
+287.44986 339.078 286.59081 339.43347 285.49707 339.43347 curveto
+284.39876 339.43347 283.53743 339.078 282.91309 338.36707 curveto
+282.29329 337.65157 281.9834 336.6672 281.9834 335.41394 curveto
+281.9834 334.15613 282.29329 333.17176 282.91309 332.46082 curveto
+283.53743 331.74989 284.39876 331.39442 285.49707 331.39441 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+290.89062 328.61218 moveto
+291.98438 328.61218 lineto
+292.66797 329.68771 293.17838 330.74045 293.51562 331.77039 curveto
+293.85742 332.80034 294.02832 333.82345 294.02832 334.83972 curveto
+294.02832 335.86056 293.85742 336.88823 293.51562 337.92273 curveto
+293.17838 338.95723 292.66797 340.00997 291.98438 341.08093 curveto
+290.89062 341.08093 lineto
+291.49674 340.03731 291.94791 339.00053 292.24414 337.97058 curveto
+292.54492 336.93608 292.69531 335.89246 292.69531 334.83972 curveto
+292.69531 333.78699 292.54492 332.74793 292.24414 331.72253 curveto
+291.94791 330.69715 291.49674 329.66037 290.89062 328.61218 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+188.1377 350.98914 moveto
+187.52701 352.03732 187.07356 353.07411 186.77734 354.09949 curveto
+186.48112 355.12488 186.33301 356.16395 186.33301 357.21667 curveto
+186.33301 358.26941 186.48112 359.31303 186.77734 360.34753 curveto
+187.07812 361.37748 187.53157 362.41427 188.1377 363.45789 curveto
+187.04395 363.45789 lineto
+186.36035 362.38692 185.84765 361.33419 185.50586 360.29968 curveto
+185.16862 359.26518 185 358.23751 185 357.21667 curveto
+185 356.2004 185.16862 355.17729 185.50586 354.14734 curveto
+185.8431 353.1174 186.35579 352.06467 187.04395 350.98914 curveto
+188.1377 350.98914 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+190.41406 351.40613 moveto
+196.97656 351.40613 lineto
+196.97656 351.99402 lineto
+193.27148 361.61218 lineto
+191.8291 361.61218 lineto
+195.31543 352.56824 lineto
+190.41406 352.56824 lineto
+190.41406 351.40613 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+199.82031 359.87585 moveto
+201.2627 359.87585 lineto
+201.2627 361.05164 lineto
+200.1416 363.23914 lineto
+199.25977 363.23914 lineto
+199.82031 361.05164 lineto
+199.82031 359.87585 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+205.32324 360.45007 moveto
+210.14258 360.45007 lineto
+210.14258 361.61218 lineto
+203.66211 361.61218 lineto
+203.66211 360.45007 lineto
+204.1862 359.90776 204.89941 359.18087 205.80176 358.26941 curveto
+206.70865 357.3534 207.27832 356.76323 207.51074 356.4989 curveto
+207.95279 356.00216 208.26041 355.58289 208.43359 355.24109 curveto
+208.61132 354.89474 208.70019 354.55522 208.7002 354.22253 curveto
+208.70019 353.68022 208.50878 353.23817 208.12598 352.89636 curveto
+207.74772 352.55457 207.25325 352.38368 206.64258 352.38367 curveto
+206.20963 352.38368 205.75162 352.45887 205.26855 352.60925 curveto
+204.79004 352.75965 204.27734 352.98752 203.73047 353.29285 curveto
+203.73047 351.89832 lineto
+204.28646 351.67502 204.80599 351.5064 205.28906 351.39246 curveto
+205.77213 351.27853 206.21419 351.22157 206.61523 351.22156 curveto
+207.67252 351.22157 208.51562 351.48589 209.14453 352.01453 curveto
+209.77343 352.54318 210.08788 353.24956 210.08789 354.13367 curveto
+210.08788 354.55294 210.00813 354.95171 209.84863 355.32996 curveto
+209.69368 355.70366 209.40885 356.14572 208.99414 356.65613 curveto
+208.8802 356.78829 208.5179 357.17111 207.90723 357.80457 curveto
+207.29654 358.43347 206.43522 359.31531 205.32324 360.45007 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+213.19141 359.87585 moveto
+214.63379 359.87585 lineto
+214.63379 361.05164 lineto
+213.5127 363.23914 lineto
+212.63086 363.23914 lineto
+213.19141 361.05164 lineto
+213.19141 359.87585 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+220.29395 354.83777 moveto
+219.61946 354.83778 219.08626 355.1021 218.69434 355.63074 curveto
+218.30241 356.15483 218.10644 356.87488 218.10645 357.79089 curveto
+218.10644 358.70691 218.30013 359.42924 218.6875 359.95789 curveto
+219.07942 360.48198 219.61491 360.74402 220.29395 360.74402 curveto
+220.96386 360.74402 221.49479 360.4797 221.88672 359.95105 curveto
+222.27864 359.42241 222.4746 358.70235 222.47461 357.79089 curveto
+222.4746 356.884 222.27864 356.16622 221.88672 355.63757 curveto
+221.49479 355.10438 220.96386 354.83778 220.29395 354.83777 curveto
+220.29395 353.77136 moveto
+221.38769 353.77137 222.24674 354.12684 222.87109 354.83777 curveto
+223.49544 355.54871 223.80761 356.53309 223.80762 357.79089 curveto
+223.80761 359.04415 223.49544 360.02853 222.87109 360.74402 curveto
+222.24674 361.45496 221.38769 361.81042 220.29395 361.81042 curveto
+219.19563 361.81042 218.33431 361.45496 217.70996 360.74402 curveto
+217.09017 360.02853 216.78027 359.04415 216.78027 357.79089 curveto
+216.78027 356.53309 217.09017 355.54871 217.70996 354.83777 curveto
+218.33431 354.12684 219.19563 353.77137 220.29395 353.77136 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+225.6875 350.98914 moveto
+226.78125 350.98914 lineto
+227.46484 352.06467 227.97526 353.1174 228.3125 354.14734 curveto
+228.65429 355.17729 228.82519 356.2004 228.8252 357.21667 curveto
+228.82519 358.23751 228.65429 359.26518 228.3125 360.29968 curveto
+227.97526 361.33419 227.46484 362.38692 226.78125 363.45789 curveto
+225.6875 363.45789 lineto
+226.29362 362.41427 226.74479 361.37748 227.04102 360.34753 curveto
+227.34179 359.31303 227.49218 358.26941 227.49219 357.21667 curveto
+227.49218 356.16395 227.34179 355.12488 227.04102 354.09949 curveto
+226.74479 353.07411 226.29362 352.03732 225.6875 350.98914 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+232.84082 350.48914 moveto
+232.23014 351.53732 231.77669 352.57411 231.48047 353.59949 curveto
+231.18424 354.62488 231.03613 355.66395 231.03613 356.71667 curveto
+231.03613 357.76941 231.18424 358.81303 231.48047 359.84753 curveto
+231.78125 360.87748 232.2347 361.91427 232.84082 362.95789 curveto
+231.74707 362.95789 lineto
+231.06347 361.88692 230.55078 360.83419 230.20898 359.79968 curveto
+229.87174 358.76518 229.70312 357.73751 229.70312 356.71667 curveto
+229.70312 355.7004 229.87174 354.67729 230.20898 353.64734 curveto
+230.54622 352.6174 231.05892 351.56467 231.74707 350.48914 curveto
+232.84082 350.48914 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+238.41895 356.2655 moveto
+237.76269 356.26551 237.24544 356.44096 236.86719 356.79187 curveto
+236.49349 357.14279 236.30664 357.62586 236.30664 358.24109 curveto
+236.30664 358.85633 236.49349 359.3394 236.86719 359.69031 curveto
+237.24544 360.04122 237.76269 360.21668 238.41895 360.21667 curveto
+239.07519 360.21668 239.59244 360.04122 239.9707 359.69031 curveto
+240.34895 359.33484 240.53808 358.85177 240.53809 358.24109 curveto
+240.53808 357.62586 240.34895 357.14279 239.9707 356.79187 curveto
+239.597 356.44096 239.07975 356.26551 238.41895 356.2655 curveto
+237.03809 355.67761 moveto
+236.44564 355.53178 235.98307 355.25607 235.65039 354.85046 curveto
+235.32226 354.44487 235.1582 353.95041 235.1582 353.36707 curveto
+235.1582 352.55132 235.44759 351.90646 236.02637 351.4325 curveto
+236.6097 350.95855 237.40722 350.72157 238.41895 350.72156 curveto
+239.43522 350.72157 240.23274 350.95855 240.81152 351.4325 curveto
+241.39029 351.90646 241.67968 352.55132 241.67969 353.36707 curveto
+241.67968 353.95041 241.51334 354.44487 241.18066 354.85046 curveto
+240.85253 355.25607 240.39452 355.53178 239.80664 355.67761 curveto
+240.472 355.83257 240.98925 356.13563 241.3584 356.58679 curveto
+241.73209 357.03797 241.91894 357.5894 241.91895 358.24109 curveto
+241.91894 359.23002 241.61588 359.98881 241.00977 360.51746 curveto
+240.4082 361.0461 239.54459 361.31042 238.41895 361.31042 curveto
+237.29329 361.31042 236.42741 361.0461 235.82129 360.51746 curveto
+235.21973 359.98881 234.91894 359.23002 234.91895 358.24109 curveto
+234.91894 357.5894 235.10579 357.03797 235.47949 356.58679 curveto
+235.85319 356.13563 236.37272 355.83257 237.03809 355.67761 curveto
+236.53223 353.49695 moveto
+236.53222 354.0256 236.69629 354.43804 237.02441 354.73425 curveto
+237.35709 355.03048 237.82194 355.17859 238.41895 355.17859 curveto
+239.01139 355.17859 239.47395 355.03048 239.80664 354.73425 curveto
+240.14387 354.43804 240.31249 354.0256 240.3125 353.49695 curveto
+240.31249 352.96831 240.14387 352.55588 239.80664 352.25964 curveto
+239.47395 351.96343 239.01139 351.81532 238.41895 351.81531 curveto
+237.82194 351.81532 237.35709 351.96343 237.02441 352.25964 curveto
+236.69629 352.55588 236.53222 352.96831 236.53223 353.49695 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+244.52344 359.37585 moveto
+245.96582 359.37585 lineto
+245.96582 360.55164 lineto
+244.84473 362.73914 lineto
+243.96289 362.73914 lineto
+244.52344 360.55164 lineto
+244.52344 359.37585 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+253.02051 355.60925 moveto
+253.68131 355.75053 254.19628 356.04448 254.56543 356.49109 curveto
+254.93912 356.93771 255.12597 357.48914 255.12598 358.14539 curveto
+255.12597 359.15255 254.77961 359.93185 254.08691 360.48328 curveto
+253.3942 361.03471 252.40983 361.31042 251.13379 361.31042 curveto
+250.7054 361.31042 250.26334 361.26713 249.80762 361.18054 curveto
+249.35644 361.09851 248.88932 360.97319 248.40625 360.80457 curveto
+248.40625 359.47156 lineto
+248.78906 359.69487 249.20833 359.86349 249.66406 359.97742 curveto
+250.11979 360.09135 250.59603 360.14832 251.09277 360.14832 curveto
+251.95865 360.14832 252.61718 359.97742 253.06836 359.63562 curveto
+253.52408 359.29383 253.75195 358.79708 253.75195 358.14539 curveto
+253.75195 357.54383 253.54003 357.07443 253.11621 356.73718 curveto
+252.69693 356.39539 252.11132 356.22449 251.35938 356.22449 curveto
+250.16992 356.22449 lineto
+250.16992 355.08972 lineto
+251.41406 355.08972 lineto
+252.09309 355.08973 252.61262 354.95529 252.97266 354.6864 curveto
+253.33268 354.41297 253.51269 354.02104 253.5127 353.51062 curveto
+253.51269 352.98654 253.32584 352.5855 252.95215 352.3075 curveto
+252.583 352.02495 252.05208 351.88368 251.35938 351.88367 curveto
+250.98112 351.88368 250.57552 351.92469 250.14258 352.00671 curveto
+249.70963 352.08875 249.2334 352.21636 248.71387 352.38953 curveto
+248.71387 351.15906 lineto
+249.23795 351.01323 249.72786 350.90386 250.18359 350.83093 curveto
+250.64388 350.75803 251.07682 350.72157 251.48242 350.72156 curveto
+252.53059 350.72157 253.36002 350.96083 253.9707 351.43933 curveto
+254.58137 351.9133 254.88671 352.55588 254.88672 353.36707 curveto
+254.88671 353.93218 254.72493 354.41069 254.40137 354.80261 curveto
+254.07779 355.18999 253.61751 355.45887 253.02051 355.60925 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+257.89453 359.37585 moveto
+259.33691 359.37585 lineto
+259.33691 360.55164 lineto
+258.21582 362.73914 lineto
+257.33398 362.73914 lineto
+257.89453 360.55164 lineto
+257.89453 359.37585 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+264.99707 354.33777 moveto
+264.32259 354.33778 263.78938 354.6021 263.39746 355.13074 curveto
+263.00553 355.65483 262.80957 356.37488 262.80957 357.29089 curveto
+262.80957 358.20691 263.00325 358.92924 263.39062 359.45789 curveto
+263.78255 359.98198 264.31803 360.24402 264.99707 360.24402 curveto
+265.66699 360.24402 266.19791 359.9797 266.58984 359.45105 curveto
+266.98176 358.92241 267.17773 358.20235 267.17773 357.29089 curveto
+267.17773 356.384 266.98176 355.66622 266.58984 355.13757 curveto
+266.19791 354.60438 265.66699 354.33778 264.99707 354.33777 curveto
+264.99707 353.27136 moveto
+266.09081 353.27137 266.94986 353.62684 267.57422 354.33777 curveto
+268.19856 355.04871 268.51073 356.03309 268.51074 357.29089 curveto
+268.51073 358.54415 268.19856 359.52853 267.57422 360.24402 curveto
+266.94986 360.95496 266.09081 361.31042 264.99707 361.31042 curveto
+263.89876 361.31042 263.03743 360.95496 262.41309 360.24402 curveto
+261.79329 359.52853 261.4834 358.54415 261.4834 357.29089 curveto
+261.4834 356.03309 261.79329 355.04871 262.41309 354.33777 curveto
+263.03743 353.62684 263.89876 353.27137 264.99707 353.27136 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+270.39062 350.48914 moveto
+271.48438 350.48914 lineto
+272.16797 351.56467 272.67838 352.6174 273.01562 353.64734 curveto
+273.35742 354.67729 273.52832 355.7004 273.52832 356.71667 curveto
+273.52832 357.73751 273.35742 358.76518 273.01562 359.79968 curveto
+272.67838 360.83419 272.16797 361.88692 271.48438 362.95789 curveto
+270.39062 362.95789 lineto
+270.99674 361.91427 271.44791 360.87748 271.74414 359.84753 curveto
+272.04492 358.81303 272.19531 357.76941 272.19531 356.71667 curveto
+272.19531 355.66395 272.04492 354.62488 271.74414 353.59949 curveto
+271.44791 352.57411 270.99674 351.53732 270.39062 350.48914 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+278.84082 350.64343 moveto
+278.23014 351.69162 277.77669 352.7284 277.48047 353.75378 curveto
+277.18424 354.77918 277.03613 355.81824 277.03613 356.87097 curveto
+277.03613 357.92371 277.18424 358.96733 277.48047 360.00183 curveto
+277.78125 361.03178 278.2347 362.06856 278.84082 363.11218 curveto
+277.74707 363.11218 lineto
+277.06347 362.04122 276.55078 360.98848 276.20898 359.95398 curveto
+275.87174 358.91948 275.70312 357.89181 275.70312 356.87097 curveto
+275.70312 355.8547 275.87174 354.83159 276.20898 353.80164 curveto
+276.54622 352.7717 277.05892 351.71896 277.74707 350.64343 curveto
+278.84082 350.64343 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+281.50684 361.05457 moveto
+281.50684 359.79675 lineto
+281.85319 359.96082 282.2041 360.08614 282.55957 360.17273 curveto
+282.91504 360.25932 283.26367 360.30261 283.60547 360.30261 curveto
+284.51692 360.30261 285.21191 359.99728 285.69043 359.3866 curveto
+286.1735 358.77136 286.44921 357.8394 286.51758 356.5907 curveto
+286.25325 356.98263 285.91829 357.28341 285.5127 357.49304 curveto
+285.10709 357.70268 284.6582 357.8075 284.16602 357.8075 curveto
+283.14518 357.8075 282.33626 357.49988 281.73926 356.88464 curveto
+281.14681 356.26486 280.85059 355.41948 280.85059 354.34851 curveto
+280.85059 353.30034 281.16048 352.45952 281.78027 351.82605 curveto
+282.40006 351.1926 283.22493 350.87586 284.25488 350.87585 curveto
+285.43522 350.87586 286.33528 351.32931 286.95508 352.23621 curveto
+287.57942 353.13856 287.89159 354.45106 287.8916 356.17371 curveto
+287.89159 357.78243 287.50878 359.06759 286.74316 360.02917 curveto
+285.98209 360.98621 284.9567 361.46472 283.66699 361.46472 curveto
+283.32063 361.46472 282.96972 361.43054 282.61426 361.36218 curveto
+282.25879 361.29382 281.88965 361.19128 281.50684 361.05457 curveto
+284.25488 356.72742 moveto
+284.87467 356.72742 285.36458 356.51551 285.72461 356.09167 curveto
+286.08919 355.66785 286.27148 355.0868 286.27148 354.34851 curveto
+286.27148 353.61479 286.08919 353.03602 285.72461 352.61218 curveto
+285.36458 352.18381 284.87467 351.96961 284.25488 351.9696 curveto
+283.63509 351.96961 283.1429 352.18381 282.77832 352.61218 curveto
+282.41829 353.03602 282.23828 353.61479 282.23828 354.34851 curveto
+282.23828 355.0868 282.41829 355.66785 282.77832 356.09167 curveto
+283.1429 356.51551 283.63509 356.72742 284.25488 356.72742 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+290.52344 359.53015 moveto
+291.96582 359.53015 lineto
+291.96582 360.70593 lineto
+290.84473 362.89343 lineto
+289.96289 362.89343 lineto
+290.52344 360.70593 lineto
+290.52344 359.53015 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+298.63086 352.26355 moveto
+295.14453 357.71179 lineto
+298.63086 357.71179 lineto
+298.63086 352.26355 lineto
+298.26855 351.06042 moveto
+300.00488 351.06042 lineto
+300.00488 357.71179 lineto
+301.46094 357.71179 lineto
+301.46094 358.86023 lineto
+300.00488 358.86023 lineto
+300.00488 361.26648 lineto
+298.63086 361.26648 lineto
+298.63086 358.86023 lineto
+294.02344 358.86023 lineto
+294.02344 357.52722 lineto
+298.26855 351.06042 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+303.89453 359.53015 moveto
+305.33691 359.53015 lineto
+305.33691 360.70593 lineto
+304.21582 362.89343 lineto
+303.33398 362.89343 lineto
+303.89453 360.70593 lineto
+303.89453 359.53015 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+310.99707 354.49207 moveto
+310.32259 354.49207 309.78938 354.75639 309.39746 355.28503 curveto
+309.00553 355.80913 308.80957 356.52918 308.80957 357.44519 curveto
+308.80957 358.36121 309.00325 359.08354 309.39062 359.61218 curveto
+309.78255 360.13627 310.31803 360.39832 310.99707 360.39832 curveto
+311.66699 360.39832 312.19791 360.13399 312.58984 359.60535 curveto
+312.98176 359.0767 313.17773 358.35665 313.17773 357.44519 curveto
+313.17773 356.53829 312.98176 355.82052 312.58984 355.29187 curveto
+312.19791 354.75867 311.66699 354.49207 310.99707 354.49207 curveto
+310.99707 353.42566 moveto
+312.09081 353.42567 312.94986 353.78114 313.57422 354.49207 curveto
+314.19856 355.20301 314.51073 356.18738 314.51074 357.44519 curveto
+314.51073 358.69845 314.19856 359.68282 313.57422 360.39832 curveto
+312.94986 361.10925 312.09081 361.46472 310.99707 361.46472 curveto
+309.89876 361.46472 309.03743 361.10925 308.41309 360.39832 curveto
+307.79329 359.68282 307.4834 358.69845 307.4834 357.44519 curveto
+307.4834 356.18738 307.79329 355.20301 308.41309 354.49207 curveto
+309.03743 353.78114 309.89876 353.42567 310.99707 353.42566 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+316.39062 350.64343 moveto
+317.48438 350.64343 lineto
+318.16797 351.71896 318.67838 352.7717 319.01562 353.80164 curveto
+319.35742 354.83159 319.52832 355.8547 319.52832 356.87097 curveto
+319.52832 357.89181 319.35742 358.91948 319.01562 359.95398 curveto
+318.67838 360.98848 318.16797 362.04122 317.48438 363.11218 curveto
+316.39062 363.11218 lineto
+316.99674 362.06856 317.44791 361.03178 317.74414 360.00183 curveto
+318.04492 358.96733 318.19531 357.92371 318.19531 356.87097 curveto
+318.19531 355.81824 318.04492 354.77918 317.74414 353.75378 curveto
+317.44791 352.7284 316.99674 351.69162 316.39062 350.64343 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+197.1377 371.14343 moveto
+196.52701 372.19162 196.07356 373.2284 195.77734 374.25378 curveto
+195.48112 375.27918 195.33301 376.31824 195.33301 377.37097 curveto
+195.33301 378.42371 195.48112 379.46733 195.77734 380.50183 curveto
+196.07812 381.53178 196.53157 382.56856 197.1377 383.61218 curveto
+196.04395 383.61218 lineto
+195.36035 382.54122 194.84765 381.48848 194.50586 380.45398 curveto
+194.16862 379.41948 194 378.39181 194 377.37097 curveto
+194 376.3547 194.16862 375.33159 194.50586 374.30164 curveto
+194.8431 373.2717 195.35579 372.21896 196.04395 371.14343 curveto
+197.1377 371.14343 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+200.00195 380.60437 moveto
+202.25781 380.60437 lineto
+202.25781 372.81824 lineto
+199.80371 373.31042 lineto
+199.80371 372.05261 lineto
+202.24414 371.56042 lineto
+203.625 371.56042 lineto
+203.625 380.60437 lineto
+205.88086 380.60437 lineto
+205.88086 381.76648 lineto
+200.00195 381.76648 lineto
+200.00195 380.60437 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+211.62988 372.4696 moveto
+210.91894 372.46961 210.38346 372.82052 210.02344 373.52234 curveto
+209.66797 374.21961 209.49023 375.27007 209.49023 376.67371 curveto
+209.49023 378.0728 209.66797 379.12325 210.02344 379.82507 curveto
+210.38346 380.52234 210.91894 380.87097 211.62988 380.87097 curveto
+212.34537 380.87097 212.88085 380.52234 213.23633 379.82507 curveto
+213.59635 379.12325 213.77636 378.0728 213.77637 376.67371 curveto
+213.77636 375.27007 213.59635 374.21961 213.23633 373.52234 curveto
+212.88085 372.82052 212.34537 372.46961 211.62988 372.4696 curveto
+211.62988 371.37585 moveto
+212.77376 371.37586 213.64648 371.82931 214.24805 372.73621 curveto
+214.85416 373.63856 215.15722 374.95106 215.15723 376.67371 curveto
+215.15722 378.39181 214.85416 379.70431 214.24805 380.61121 curveto
+213.64648 381.51355 212.77376 381.96472 211.62988 381.96472 curveto
+210.486 381.96472 209.611 381.51355 209.00488 380.61121 curveto
+208.40332 379.70431 208.10254 378.39181 208.10254 376.67371 curveto
+208.10254 374.95106 208.40332 373.63856 209.00488 372.73621 curveto
+209.611 371.82931 210.486 371.37586 211.62988 371.37585 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+217.73438 380.03015 moveto
+219.17676 380.03015 lineto
+219.17676 381.20593 lineto
+218.05566 383.39343 lineto
+217.17383 383.39343 lineto
+217.73438 381.20593 lineto
+217.73438 380.03015 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+222.06152 371.56042 moveto
+227.48242 371.56042 lineto
+227.48242 372.72253 lineto
+223.32617 372.72253 lineto
+223.32617 375.22449 lineto
+223.52669 375.15613 223.72721 375.106 223.92773 375.0741 curveto
+224.12825 375.03765 224.32877 375.01942 224.5293 375.01941 curveto
+225.66861 375.01942 226.57096 375.33159 227.23633 375.95593 curveto
+227.90169 376.58029 228.23437 377.42566 228.23438 378.49207 curveto
+228.23437 379.59037 227.89257 380.44487 227.20898 381.05554 curveto
+226.52538 381.66166 225.56152 381.96472 224.31738 381.96472 curveto
+223.88899 381.96472 223.45149 381.92826 223.00488 381.85535 curveto
+222.56282 381.78243 222.10482 381.67306 221.63086 381.52722 curveto
+221.63086 380.13953 lineto
+222.04101 380.36284 222.46484 380.52918 222.90234 380.63855 curveto
+223.33984 380.74793 223.80241 380.80261 224.29004 380.80261 curveto
+225.07845 380.80261 225.70279 380.59526 226.16309 380.18054 curveto
+226.62337 379.76583 226.85351 379.20301 226.85352 378.49207 curveto
+226.85351 377.78113 226.62337 377.21831 226.16309 376.80359 curveto
+225.70279 376.38888 225.07845 376.18152 224.29004 376.18152 curveto
+223.9209 376.18152 223.55175 376.22254 223.18262 376.30457 curveto
+222.81803 376.3866 222.44433 376.51421 222.06152 376.68738 curveto
+222.06152 371.56042 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+231.10547 380.03015 moveto
+232.54785 380.03015 lineto
+232.54785 381.20593 lineto
+231.42676 383.39343 lineto
+230.54492 383.39343 lineto
+231.10547 381.20593 lineto
+231.10547 380.03015 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+238.20801 374.99207 moveto
+237.53353 374.99207 237.00032 375.25639 236.6084 375.78503 curveto
+236.21647 376.30913 236.02051 377.02918 236.02051 377.94519 curveto
+236.02051 378.86121 236.21419 379.58354 236.60156 380.11218 curveto
+236.99349 380.63627 237.52897 380.89832 238.20801 380.89832 curveto
+238.87792 380.89832 239.40885 380.63399 239.80078 380.10535 curveto
+240.1927 379.5767 240.38867 378.85665 240.38867 377.94519 curveto
+240.38867 377.03829 240.1927 376.32052 239.80078 375.79187 curveto
+239.40885 375.25867 238.87792 374.99207 238.20801 374.99207 curveto
+238.20801 373.92566 moveto
+239.30175 373.92567 240.1608 374.28114 240.78516 374.99207 curveto
+241.4095 375.70301 241.72167 376.68738 241.72168 377.94519 curveto
+241.72167 379.19845 241.4095 380.18282 240.78516 380.89832 curveto
+240.1608 381.60925 239.30175 381.96472 238.20801 381.96472 curveto
+237.1097 381.96472 236.24837 381.60925 235.62402 380.89832 curveto
+235.00423 380.18282 234.69434 379.19845 234.69434 377.94519 curveto
+234.69434 376.68738 235.00423 375.70301 235.62402 374.99207 curveto
+236.24837 374.28114 237.1097 373.92567 238.20801 373.92566 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+243.60156 371.14343 moveto
+244.69531 371.14343 lineto
+245.3789 372.21896 245.88932 373.2717 246.22656 374.30164 curveto
+246.56836 375.33159 246.73925 376.3547 246.73926 377.37097 curveto
+246.73925 378.39181 246.56836 379.41948 246.22656 380.45398 curveto
+245.88932 381.48848 245.3789 382.54122 244.69531 383.61218 curveto
+243.60156 383.61218 lineto
+244.20768 382.56856 244.65885 381.53178 244.95508 380.50183 curveto
+245.25586 379.46733 245.40625 378.42371 245.40625 377.37097 curveto
+245.40625 376.31824 245.25586 375.27918 244.95508 374.25378 curveto
+244.65885 373.2284 244.20768 372.19162 243.60156 371.14343 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+252.1377 371.98914 moveto
+251.52701 373.03732 251.07356 374.07411 250.77734 375.09949 curveto
+250.48112 376.12488 250.33301 377.16395 250.33301 378.21667 curveto
+250.33301 379.26941 250.48112 380.31303 250.77734 381.34753 curveto
+251.07812 382.37748 251.53157 383.41427 252.1377 384.45789 curveto
+251.04395 384.45789 lineto
+250.36035 383.38692 249.84765 382.33419 249.50586 381.29968 curveto
+249.16862 380.26518 249 379.23751 249 378.21667 curveto
+249 377.2004 249.16862 376.17729 249.50586 375.14734 curveto
+249.8431 374.1174 250.35579 373.06467 251.04395 371.98914 curveto
+252.1377 371.98914 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+255.00195 381.45007 moveto
+257.25781 381.45007 lineto
+257.25781 373.66394 lineto
+254.80371 374.15613 lineto
+254.80371 372.89832 lineto
+257.24414 372.40613 lineto
+258.625 372.40613 lineto
+258.625 381.45007 lineto
+260.88086 381.45007 lineto
+260.88086 382.61218 lineto
+255.00195 382.61218 lineto
+255.00195 381.45007 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+263.91602 381.45007 moveto
+266.17188 381.45007 lineto
+266.17188 373.66394 lineto
+263.71777 374.15613 lineto
+263.71777 372.89832 lineto
+266.1582 372.40613 lineto
+267.53906 372.40613 lineto
+267.53906 381.45007 lineto
+269.79492 381.45007 lineto
+269.79492 382.61218 lineto
+263.91602 382.61218 lineto
+263.91602 381.45007 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+272.73438 380.87585 moveto
+274.17676 380.87585 lineto
+274.17676 382.05164 lineto
+273.05566 384.23914 lineto
+272.17383 384.23914 lineto
+272.73438 382.05164 lineto
+272.73438 380.87585 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+280.17188 376.95886 moveto
+279.55208 376.95887 279.05989 377.17078 278.69531 377.5946 curveto
+278.33528 378.01844 278.15527 378.59949 278.15527 379.33777 curveto
+278.15527 380.0715 278.33528 380.65255 278.69531 381.08093 curveto
+279.05989 381.50476 279.55208 381.71668 280.17188 381.71667 curveto
+280.79166 381.71668 281.28157 381.50476 281.6416 381.08093 curveto
+282.00618 380.65255 282.18847 380.0715 282.18848 379.33777 curveto
+282.18847 378.59949 282.00618 378.01844 281.6416 377.5946 curveto
+281.28157 377.17078 280.79166 376.95887 280.17188 376.95886 curveto
+282.91309 372.63171 moveto
+282.91309 373.88953 lineto
+282.56672 373.72547 282.21581 373.60015 281.86035 373.51355 curveto
+281.50943 373.42697 281.1608 373.38368 280.81445 373.38367 curveto
+279.90299 373.38368 279.20573 373.69129 278.72266 374.30652 curveto
+278.24414 374.92176 277.9707 375.85145 277.90234 377.09558 curveto
+278.17122 376.6991 278.50846 376.39604 278.91406 376.1864 curveto
+279.31966 375.97222 279.76627 375.86512 280.25391 375.86511 curveto
+281.27929 375.86512 282.08821 376.17729 282.68066 376.80164 curveto
+283.27766 377.42143 283.57616 378.26681 283.57617 379.33777 curveto
+283.57616 380.38595 283.26627 381.22677 282.64648 381.86023 curveto
+282.02669 382.49369 281.20182 382.81042 280.17188 382.81042 curveto
+278.99153 382.81042 278.08919 382.35925 277.46484 381.45691 curveto
+276.84049 380.55001 276.52832 379.23751 276.52832 377.51941 curveto
+276.52832 375.90613 276.91113 374.62098 277.67676 373.66394 curveto
+278.44238 372.70236 279.47005 372.22157 280.75977 372.22156 curveto
+281.10611 372.22157 281.45475 372.25575 281.80566 372.3241 curveto
+282.16113 372.39247 282.53027 372.49501 282.91309 372.63171 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+286.10547 380.87585 moveto
+287.54785 380.87585 lineto
+287.54785 382.05164 lineto
+286.42676 384.23914 lineto
+285.54492 384.23914 lineto
+286.10547 382.05164 lineto
+286.10547 380.87585 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+293.20801 375.83777 moveto
+292.53353 375.83778 292.00032 376.1021 291.6084 376.63074 curveto
+291.21647 377.15483 291.02051 377.87488 291.02051 378.79089 curveto
+291.02051 379.70691 291.21419 380.42924 291.60156 380.95789 curveto
+291.99349 381.48198 292.52897 381.74402 293.20801 381.74402 curveto
+293.87792 381.74402 294.40885 381.4797 294.80078 380.95105 curveto
+295.1927 380.42241 295.38867 379.70235 295.38867 378.79089 curveto
+295.38867 377.884 295.1927 377.16622 294.80078 376.63757 curveto
+294.40885 376.10438 293.87792 375.83778 293.20801 375.83777 curveto
+293.20801 374.77136 moveto
+294.30175 374.77137 295.1608 375.12684 295.78516 375.83777 curveto
+296.4095 376.54871 296.72167 377.53309 296.72168 378.79089 curveto
+296.72167 380.04415 296.4095 381.02853 295.78516 381.74402 curveto
+295.1608 382.45496 294.30175 382.81042 293.20801 382.81042 curveto
+292.1097 382.81042 291.24837 382.45496 290.62402 381.74402 curveto
+290.00423 381.02853 289.69434 380.04415 289.69434 378.79089 curveto
+289.69434 377.53309 290.00423 376.54871 290.62402 375.83777 curveto
+291.24837 375.12684 292.1097 374.77137 293.20801 374.77136 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+298.60156 371.98914 moveto
+299.69531 371.98914 lineto
+300.3789 373.06467 300.88932 374.1174 301.22656 375.14734 curveto
+301.56836 376.17729 301.73925 377.2004 301.73926 378.21667 curveto
+301.73925 379.23751 301.56836 380.26518 301.22656 381.29968 curveto
+300.88932 382.33419 300.3789 383.38692 299.69531 384.45789 curveto
+298.60156 384.45789 lineto
+299.20768 383.41427 299.65885 382.37748 299.95508 381.34753 curveto
+300.25586 380.31303 300.40625 379.26941 300.40625 378.21667 curveto
+300.40625 377.16395 300.25586 376.12488 299.95508 375.09949 curveto
+299.65885 374.07411 299.20768 373.03732 298.60156 371.98914 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+238.37402 312.40613 moveto
+239.75488 312.40613 lineto
+239.75488 322.61218 lineto
+238.37402 322.61218 lineto
+238.37402 312.40613 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+247.3291 315.18152 moveto
+247.3291 316.37097 lineto
+246.97363 316.18869 246.60449 316.05197 246.22168 315.96082 curveto
+245.83886 315.86968 245.44238 315.8241 245.03223 315.8241 curveto
+244.40787 315.8241 243.93847 315.91981 243.62402 316.11121 curveto
+243.31413 316.30262 243.15918 316.58973 243.15918 316.97253 curveto
+243.15918 317.26421 243.27083 317.49435 243.49414 317.66296 curveto
+243.71745 317.82703 244.16634 317.98426 244.84082 318.13464 curveto
+245.27148 318.23035 lineto
+246.16471 318.42176 246.79817 318.69292 247.17188 319.04382 curveto
+247.55012 319.39018 247.73925 319.87553 247.73926 320.49988 curveto
+247.73925 321.21082 247.4567 321.77364 246.8916 322.18835 curveto
+246.33105 322.60307 245.55859 322.81042 244.57422 322.81042 curveto
+244.16406 322.81042 243.73567 322.76941 243.28906 322.68738 curveto
+242.847 322.6099 242.37988 322.49141 241.8877 322.33191 curveto
+241.8877 321.03308 lineto
+242.35254 321.27462 242.81055 321.45691 243.26172 321.57996 curveto
+243.71289 321.69845 244.1595 321.75769 244.60156 321.75769 curveto
+245.19401 321.75769 245.64974 321.65743 245.96875 321.45691 curveto
+246.28776 321.25183 246.44726 320.96472 246.44727 320.59558 curveto
+246.44726 320.25379 246.33105 319.99174 246.09863 319.80945 curveto
+245.87076 319.62716 245.36718 319.4517 244.58789 319.28308 curveto
+244.15039 319.18054 lineto
+243.37109 319.01648 242.80827 318.76583 242.46191 318.42859 curveto
+242.11556 318.0868 241.94238 317.61967 241.94238 317.02722 curveto
+241.94238 316.30718 242.19759 315.75119 242.70801 315.35925 curveto
+243.21842 314.96733 243.94303 314.77137 244.88184 314.77136 curveto
+245.34668 314.77137 245.78418 314.80555 246.19434 314.8739 curveto
+246.60449 314.94227 246.98274 315.04481 247.3291 315.18152 curveto
+fill
+grestore
+gsave [1 0 0 1 3.250285 1] concat
+gsave
+0 0 0 setrgbcolor
+newpath
+180.84082 436.23914 moveto
+180.23014 437.28732 179.77669 438.32411 179.48047 439.34949 curveto
+179.18424 440.37488 179.03613 441.41395 179.03613 442.46667 curveto
+179.03613 443.51941 179.18424 444.56303 179.48047 445.59753 curveto
+179.78125 446.62748 180.2347 447.66427 180.84082 448.70789 curveto
+179.74707 448.70789 lineto
+179.06347 447.63692 178.55078 446.58419 178.20898 445.54968 curveto
+177.87174 444.51518 177.70312 443.48751 177.70312 442.46667 curveto
+177.70312 441.4504 177.87174 440.42729 178.20898 439.39734 curveto
+178.54622 438.3674 179.05892 437.31467 179.74707 436.23914 curveto
+180.84082 436.23914 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+184.65527 445.70007 moveto
+189.47461 445.70007 lineto
+189.47461 446.86218 lineto
+182.99414 446.86218 lineto
+182.99414 445.70007 lineto
+183.51823 445.15776 184.23144 444.43087 185.13379 443.51941 curveto
+186.04069 442.6034 186.61035 442.01323 186.84277 441.7489 curveto
+187.28483 441.25216 187.59244 440.83289 187.76562 440.49109 curveto
+187.94335 440.14474 188.03222 439.80522 188.03223 439.47253 curveto
+188.03222 438.93022 187.84081 438.48817 187.45801 438.14636 curveto
+187.07975 437.80457 186.58528 437.63368 185.97461 437.63367 curveto
+185.54166 437.63368 185.08366 437.70887 184.60059 437.85925 curveto
+184.12207 438.00965 183.60937 438.23752 183.0625 438.54285 curveto
+183.0625 437.14832 lineto
+183.61849 436.92502 184.13802 436.7564 184.62109 436.64246 curveto
+185.10416 436.52853 185.54622 436.47157 185.94727 436.47156 curveto
+187.00455 436.47157 187.84765 436.73589 188.47656 437.26453 curveto
+189.10546 437.79318 189.41991 438.49956 189.41992 439.38367 curveto
+189.41991 439.80294 189.34016 440.20171 189.18066 440.57996 curveto
+189.02571 440.95366 188.74088 441.39572 188.32617 441.90613 curveto
+188.21223 442.03829 187.84993 442.42111 187.23926 443.05457 curveto
+186.62858 443.68347 185.76725 444.56531 184.65527 445.70007 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+192.52344 445.12585 moveto
+193.96582 445.12585 lineto
+193.96582 446.30164 lineto
+192.84473 448.48914 lineto
+191.96289 448.48914 lineto
+192.52344 446.30164 lineto
+192.52344 445.12585 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+199.79004 437.56531 moveto
+199.0791 437.56532 198.54362 437.91623 198.18359 438.61804 curveto
+197.82812 439.31532 197.65039 440.36577 197.65039 441.76941 curveto
+197.65039 443.1685 197.82812 444.21896 198.18359 444.92078 curveto
+198.54362 445.61804 199.0791 445.96668 199.79004 445.96667 curveto
+200.50553 445.96668 201.04101 445.61804 201.39648 444.92078 curveto
+201.7565 444.21896 201.93652 443.1685 201.93652 441.76941 curveto
+201.93652 440.36577 201.7565 439.31532 201.39648 438.61804 curveto
+201.04101 437.91623 200.50553 437.56532 199.79004 437.56531 curveto
+199.79004 436.47156 moveto
+200.93391 436.47157 201.80663 436.92502 202.4082 437.83191 curveto
+203.01432 438.73426 203.31737 440.04676 203.31738 441.76941 curveto
+203.31737 443.48751 203.01432 444.80001 202.4082 445.70691 curveto
+201.80663 446.60925 200.93391 447.06042 199.79004 447.06042 curveto
+198.64616 447.06042 197.77116 446.60925 197.16504 445.70691 curveto
+196.56348 444.80001 196.26269 443.48751 196.2627 441.76941 curveto
+196.26269 440.04676 196.56348 438.73426 197.16504 437.83191 curveto
+197.77116 436.92502 198.64616 436.47157 199.79004 436.47156 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+205.89453 445.12585 moveto
+207.33691 445.12585 lineto
+207.33691 446.30164 lineto
+206.21582 448.48914 lineto
+205.33398 448.48914 lineto
+205.89453 446.30164 lineto
+205.89453 445.12585 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+215.06836 442.94519 moveto
+215.06835 442.03374 214.87923 441.32736 214.50098 440.82605 curveto
+214.12727 440.32475 213.60091 440.0741 212.92188 440.0741 curveto
+212.24739 440.0741 211.72103 440.32475 211.34277 440.82605 curveto
+210.96907 441.32736 210.78222 442.03374 210.78223 442.94519 curveto
+210.78222 443.85209 210.96907 444.5562 211.34277 445.0575 curveto
+211.72103 445.5588 212.24739 445.80945 212.92188 445.80945 curveto
+213.60091 445.80945 214.12727 445.5588 214.50098 445.0575 curveto
+214.87923 444.5562 215.06835 443.85209 215.06836 442.94519 curveto
+216.32617 445.91199 moveto
+216.32616 447.21537 216.03678 448.1838 215.45801 448.81726 curveto
+214.87923 449.45528 213.99283 449.77429 212.79883 449.77429 curveto
+212.35677 449.77429 211.93978 449.74011 211.54785 449.67175 curveto
+211.15592 449.60795 210.77539 449.50769 210.40625 449.37097 curveto
+210.40625 448.14734 lineto
+210.77539 448.34786 211.13997 448.49597 211.5 448.59167 curveto
+211.86002 448.68738 212.22688 448.73523 212.60059 448.73523 curveto
+213.42545 448.73523 214.04296 448.51876 214.45312 448.08582 curveto
+214.86328 447.65743 215.06835 447.00802 215.06836 446.13757 curveto
+215.06836 445.5155 lineto
+214.80859 445.96668 214.47591 446.30391 214.07031 446.52722 curveto
+213.66471 446.75053 213.17936 446.86218 212.61426 446.86218 curveto
+211.67545 446.86218 210.91894 446.50444 210.34473 445.78894 curveto
+209.77051 445.07345 209.4834 444.12553 209.4834 442.94519 curveto
+209.4834 441.7603 209.77051 440.81011 210.34473 440.0946 curveto
+210.91894 439.37912 211.67545 439.02137 212.61426 439.02136 curveto
+213.17936 439.02137 213.66471 439.13302 214.07031 439.35632 curveto
+214.47591 439.57964 214.80859 439.91688 215.06836 440.36804 curveto
+215.06836 439.20593 lineto
+216.32617 439.20593 lineto
+216.32617 445.91199 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+218.71875 436.23914 moveto
+219.8125 436.23914 lineto
+220.49609 437.31467 221.00651 438.3674 221.34375 439.39734 curveto
+221.68554 440.42729 221.85644 441.4504 221.85645 442.46667 curveto
+221.85644 443.48751 221.68554 444.51518 221.34375 445.54968 curveto
+221.00651 446.58419 220.49609 447.63692 219.8125 448.70789 curveto
+218.71875 448.70789 lineto
+219.32487 447.66427 219.77604 446.62748 220.07227 445.59753 curveto
+220.37304 444.56303 220.52343 443.51941 220.52344 442.46667 curveto
+220.52343 441.41395 220.37304 440.37488 220.07227 439.34949 curveto
+219.77604 438.32411 219.32487 437.28732 218.71875 436.23914 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+228.53711 436.77234 moveto
+227.92643 437.82053 227.47298 438.85731 227.17676 439.88269 curveto
+226.88053 440.90809 226.73242 441.94715 226.73242 442.99988 curveto
+226.73242 444.05262 226.88053 445.09623 227.17676 446.13074 curveto
+227.47754 447.16069 227.93099 448.19747 228.53711 449.24109 curveto
+227.44336 449.24109 lineto
+226.75976 448.17012 226.24707 447.11739 225.90527 446.08289 curveto
+225.56803 445.04838 225.39941 444.02071 225.39941 442.99988 curveto
+225.39941 441.98361 225.56803 440.9605 225.90527 439.93054 curveto
+226.24251 438.9006 226.75521 437.84787 227.44336 436.77234 curveto
+228.53711 436.77234 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+235.3457 441.89246 moveto
+236.0065 442.03374 236.52148 442.32768 236.89062 442.77429 curveto
+237.26432 443.22091 237.45116 443.77234 237.45117 444.42859 curveto
+237.45116 445.43575 237.10481 446.21505 236.41211 446.76648 curveto
+235.71939 447.31791 234.73502 447.59363 233.45898 447.59363 curveto
+233.0306 447.59363 232.58854 447.55033 232.13281 447.46375 curveto
+231.68164 447.38171 231.21452 447.25639 230.73145 447.08777 curveto
+230.73145 445.75476 lineto
+231.11426 445.97807 231.53353 446.14669 231.98926 446.26062 curveto
+232.44498 446.37455 232.92122 446.43152 233.41797 446.43152 curveto
+234.28385 446.43152 234.94238 446.26062 235.39355 445.91882 curveto
+235.84928 445.57703 236.07714 445.08028 236.07715 444.42859 curveto
+236.07714 443.82703 235.86523 443.35763 235.44141 443.02039 curveto
+235.02213 442.67859 234.43652 442.5077 233.68457 442.50769 curveto
+232.49512 442.50769 lineto
+232.49512 441.37292 lineto
+233.73926 441.37292 lineto
+234.41829 441.37293 234.93782 441.23849 235.29785 440.9696 curveto
+235.65787 440.69617 235.83788 440.30425 235.83789 439.79382 curveto
+235.83788 439.26974 235.65104 438.8687 235.27734 438.5907 curveto
+234.9082 438.30816 234.37727 438.16688 233.68457 438.16687 curveto
+233.30631 438.16688 232.90071 438.20789 232.46777 438.28992 curveto
+232.03483 438.37196 231.55859 438.49956 231.03906 438.67273 curveto
+231.03906 437.44226 lineto
+231.56315 437.29644 232.05306 437.18706 232.50879 437.11414 curveto
+232.96907 437.04123 233.40201 437.00477 233.80762 437.00476 curveto
+234.85579 437.00477 235.68522 437.24403 236.2959 437.72253 curveto
+236.90657 438.1965 237.21191 438.83908 237.21191 439.65027 curveto
+237.21191 440.21538 237.05012 440.6939 236.72656 441.08582 curveto
+236.40299 441.47319 235.9427 441.74207 235.3457 441.89246 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+240.21973 445.65906 moveto
+241.66211 445.65906 lineto
+241.66211 446.83484 lineto
+240.54102 449.02234 lineto
+239.65918 449.02234 lineto
+240.21973 446.83484 lineto
+240.21973 445.65906 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+244.77246 446.23328 moveto
+247.02832 446.23328 lineto
+247.02832 438.44714 lineto
+244.57422 438.93933 lineto
+244.57422 437.68152 lineto
+247.01465 437.18933 lineto
+248.39551 437.18933 lineto
+248.39551 446.23328 lineto
+250.65137 446.23328 lineto
+250.65137 447.39539 lineto
+244.77246 447.39539 lineto
+244.77246 446.23328 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+253.59082 445.65906 moveto
+255.0332 445.65906 lineto
+255.0332 446.83484 lineto
+253.91211 449.02234 lineto
+253.03027 449.02234 lineto
+253.59082 446.83484 lineto
+253.59082 445.65906 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+260.69336 440.62097 moveto
+260.01888 440.62098 259.48567 440.8853 259.09375 441.41394 curveto
+258.70182 441.93803 258.50586 442.65809 258.50586 443.5741 curveto
+258.50586 444.49012 258.69954 445.21245 259.08691 445.74109 curveto
+259.47884 446.26518 260.01432 446.52722 260.69336 446.52722 curveto
+261.36328 446.52722 261.8942 446.2629 262.28613 445.73425 curveto
+262.67805 445.20561 262.87402 444.48556 262.87402 443.5741 curveto
+262.87402 442.6672 262.67805 441.94943 262.28613 441.42078 curveto
+261.8942 440.88758 261.36328 440.62098 260.69336 440.62097 curveto
+260.69336 439.55457 moveto
+261.7871 439.55457 262.64615 439.91004 263.27051 440.62097 curveto
+263.89485 441.33192 264.20702 442.31629 264.20703 443.5741 curveto
+264.20702 444.82735 263.89485 445.81173 263.27051 446.52722 curveto
+262.64615 447.23816 261.7871 447.59363 260.69336 447.59363 curveto
+259.59505 447.59363 258.73372 447.23816 258.10938 446.52722 curveto
+257.48958 445.81173 257.17969 444.82735 257.17969 443.5741 curveto
+257.17969 442.31629 257.48958 441.33192 258.10938 440.62097 curveto
+258.73372 439.91004 259.59505 439.55457 260.69336 439.55457 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+266.08691 436.77234 moveto
+267.18066 436.77234 lineto
+267.86425 437.84787 268.37467 438.9006 268.71191 439.93054 curveto
+269.05371 440.9605 269.22461 441.98361 269.22461 442.99988 curveto
+269.22461 444.02071 269.05371 445.04838 268.71191 446.08289 curveto
+268.37467 447.11739 267.86425 448.17012 267.18066 449.24109 curveto
+266.08691 449.24109 lineto
+266.69303 448.19747 267.1442 447.16069 267.44043 446.13074 curveto
+267.74121 445.09623 267.8916 444.05262 267.8916 442.99988 curveto
+267.8916 441.94715 267.74121 440.90809 267.44043 439.88269 curveto
+267.1442 438.85731 266.69303 437.82053 266.08691 436.77234 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+275.5498 436.77234 moveto
+274.93912 437.82053 274.48567 438.85731 274.18945 439.88269 curveto
+273.89323 440.90809 273.74511 441.94715 273.74512 442.99988 curveto
+273.74511 444.05262 273.89323 445.09623 274.18945 446.13074 curveto
+274.49023 447.16069 274.94368 448.19747 275.5498 449.24109 curveto
+274.45605 449.24109 lineto
+273.77246 448.17012 273.25976 447.11739 272.91797 446.08289 curveto
+272.58073 445.04838 272.41211 444.02071 272.41211 442.99988 curveto
+272.41211 441.98361 272.58073 440.9605 272.91797 439.93054 curveto
+273.25521 438.9006 273.7679 437.84787 274.45605 436.77234 curveto
+275.5498 436.77234 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+281.96875 438.39246 moveto
+278.48242 443.8407 lineto
+281.96875 443.8407 lineto
+281.96875 438.39246 lineto
+281.60645 437.18933 moveto
+283.34277 437.18933 lineto
+283.34277 443.8407 lineto
+284.79883 443.8407 lineto
+284.79883 444.98914 lineto
+283.34277 444.98914 lineto
+283.34277 447.39539 lineto
+281.96875 447.39539 lineto
+281.96875 444.98914 lineto
+277.36133 444.98914 lineto
+277.36133 443.65613 lineto
+281.60645 437.18933 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+287.23242 445.65906 moveto
+288.6748 445.65906 lineto
+288.6748 446.83484 lineto
+287.55371 449.02234 lineto
+286.67188 449.02234 lineto
+287.23242 446.83484 lineto
+287.23242 445.65906 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+292.73535 446.23328 moveto
+297.55469 446.23328 lineto
+297.55469 447.39539 lineto
+291.07422 447.39539 lineto
+291.07422 446.23328 lineto
+291.59831 445.69096 292.31152 444.96407 293.21387 444.05261 curveto
+294.12076 443.1366 294.69043 442.54643 294.92285 442.2821 curveto
+295.3649 441.78537 295.67252 441.36609 295.8457 441.02429 curveto
+296.02343 440.67794 296.1123 440.33843 296.1123 440.00574 curveto
+296.1123 439.46343 295.92089 439.02137 295.53809 438.67957 curveto
+295.15983 438.33778 294.66536 438.16688 294.05469 438.16687 curveto
+293.62174 438.16688 293.16373 438.24207 292.68066 438.39246 curveto
+292.20215 438.54286 291.68945 438.77072 291.14258 439.07605 curveto
+291.14258 437.68152 lineto
+291.69857 437.45822 292.2181 437.2896 292.70117 437.17566 curveto
+293.18424 437.06174 293.6263 437.00477 294.02734 437.00476 curveto
+295.08463 437.00477 295.92773 437.26909 296.55664 437.79773 curveto
+297.18554 438.32638 297.49999 439.03276 297.5 439.91687 curveto
+297.49999 440.33615 297.42024 440.73491 297.26074 441.11316 curveto
+297.10579 441.48686 296.82096 441.92892 296.40625 442.43933 curveto
+296.29231 442.5715 295.93001 442.95431 295.31934 443.58777 curveto
+294.70865 444.21668 293.84733 445.09851 292.73535 446.23328 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+300.60352 445.65906 moveto
+302.0459 445.65906 lineto
+302.0459 446.83484 lineto
+300.9248 449.02234 lineto
+300.04297 449.02234 lineto
+300.60352 446.83484 lineto
+300.60352 445.65906 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+307.70605 440.62097 moveto
+307.03157 440.62098 306.49837 440.8853 306.10645 441.41394 curveto
+305.71452 441.93803 305.51855 442.65809 305.51855 443.5741 curveto
+305.51855 444.49012 305.71224 445.21245 306.09961 445.74109 curveto
+306.49153 446.26518 307.02701 446.52722 307.70605 446.52722 curveto
+308.37597 446.52722 308.9069 446.2629 309.29883 445.73425 curveto
+309.69075 445.20561 309.88671 444.48556 309.88672 443.5741 curveto
+309.88671 442.6672 309.69075 441.94943 309.29883 441.42078 curveto
+308.9069 440.88758 308.37597 440.62098 307.70605 440.62097 curveto
+307.70605 439.55457 moveto
+308.7998 439.55457 309.65885 439.91004 310.2832 440.62097 curveto
+310.90754 441.33192 311.21972 442.31629 311.21973 443.5741 curveto
+311.21972 444.82735 310.90754 445.81173 310.2832 446.52722 curveto
+309.65885 447.23816 308.7998 447.59363 307.70605 447.59363 curveto
+306.60774 447.59363 305.74642 447.23816 305.12207 446.52722 curveto
+304.50228 445.81173 304.19238 444.82735 304.19238 443.5741 curveto
+304.19238 442.31629 304.50228 441.33192 305.12207 440.62097 curveto
+305.74642 439.91004 306.60774 439.55457 307.70605 439.55457 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+313.09961 436.77234 moveto
+314.19336 436.77234 lineto
+314.87695 437.84787 315.38737 438.9006 315.72461 439.93054 curveto
+316.0664 440.9605 316.2373 441.98361 316.2373 442.99988 curveto
+316.2373 444.02071 316.0664 445.04838 315.72461 446.08289 curveto
+315.38737 447.11739 314.87695 448.17012 314.19336 449.24109 curveto
+313.09961 449.24109 lineto
+313.70573 448.19747 314.1569 447.16069 314.45312 446.13074 curveto
+314.7539 445.09623 314.90429 444.05262 314.9043 442.99988 curveto
+314.90429 441.94715 314.7539 440.90809 314.45312 439.88269 curveto
+314.1569 438.85731 313.70573 437.82053 313.09961 436.77234 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+181.16895 456.3075 moveto
+180.55826 457.35568 180.10481 458.39246 179.80859 459.41785 curveto
+179.51237 460.44324 179.36426 461.48231 179.36426 462.53503 curveto
+179.36426 463.58777 179.51237 464.63139 179.80859 465.66589 curveto
+180.10937 466.69584 180.56282 467.73262 181.16895 468.77625 curveto
+180.0752 468.77625 lineto
+179.3916 467.70528 178.8789 466.65255 178.53711 465.61804 curveto
+178.19987 464.58354 178.03125 463.55587 178.03125 462.53503 curveto
+178.03125 461.51876 178.19987 460.49565 178.53711 459.4657 curveto
+178.87435 458.43576 179.38704 457.38303 180.0752 456.3075 curveto
+181.16895 456.3075 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+183.80762 456.72449 moveto
+189.22852 456.72449 lineto
+189.22852 457.8866 lineto
+185.07227 457.8866 lineto
+185.07227 460.38855 lineto
+185.27278 460.3202 185.4733 460.27007 185.67383 460.23816 curveto
+185.87435 460.20171 186.07487 460.18348 186.27539 460.18347 curveto
+187.41471 460.18348 188.31705 460.49565 188.98242 461.12 curveto
+189.64778 461.74435 189.98046 462.58973 189.98047 463.65613 curveto
+189.98046 464.75444 189.63866 465.60893 188.95508 466.2196 curveto
+188.27148 466.82572 187.30761 467.12878 186.06348 467.12878 curveto
+185.63509 467.12878 185.19759 467.09233 184.75098 467.01941 curveto
+184.30892 466.94649 183.85091 466.83712 183.37695 466.69128 curveto
+183.37695 465.30359 lineto
+183.78711 465.5269 184.21094 465.69324 184.64844 465.80261 curveto
+185.08593 465.91199 185.5485 465.96668 186.03613 465.96667 curveto
+186.82454 465.96668 187.44889 465.75932 187.90918 465.3446 curveto
+188.36946 464.92989 188.5996 464.36707 188.59961 463.65613 curveto
+188.5996 462.94519 188.36946 462.38237 187.90918 461.96765 curveto
+187.44889 461.55294 186.82454 461.34559 186.03613 461.34558 curveto
+185.66699 461.34559 185.29785 461.3866 184.92871 461.46863 curveto
+184.56413 461.55066 184.19043 461.67827 183.80762 461.85144 curveto
+183.80762 456.72449 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+192.85156 465.19421 moveto
+194.29395 465.19421 lineto
+194.29395 466.37 lineto
+193.17285 468.5575 lineto
+192.29102 468.5575 lineto
+192.85156 466.37 lineto
+192.85156 465.19421 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+201.34863 461.42761 moveto
+202.00943 461.56889 202.52441 461.86284 202.89355 462.30945 curveto
+203.26725 462.75607 203.45409 463.3075 203.4541 463.96375 curveto
+203.45409 464.97091 203.10774 465.7502 202.41504 466.30164 curveto
+201.72232 466.85307 200.73795 467.12878 199.46191 467.12878 curveto
+199.03353 467.12878 198.59147 467.08549 198.13574 466.9989 curveto
+197.68457 466.91687 197.21745 466.79154 196.73438 466.62292 curveto
+196.73438 465.28992 lineto
+197.11719 465.51323 197.53646 465.68185 197.99219 465.79578 curveto
+198.44791 465.90971 198.92415 465.96668 199.4209 465.96667 curveto
+200.28678 465.96668 200.94531 465.79578 201.39648 465.45398 curveto
+201.85221 465.11218 202.08007 464.61544 202.08008 463.96375 curveto
+202.08007 463.36219 201.86816 462.89279 201.44434 462.55554 curveto
+201.02506 462.21375 200.43945 462.04285 199.6875 462.04285 curveto
+198.49805 462.04285 lineto
+198.49805 460.90808 lineto
+199.74219 460.90808 lineto
+200.42122 460.90809 200.94075 460.77365 201.30078 460.50476 curveto
+201.6608 460.23133 201.84081 459.8394 201.84082 459.32898 curveto
+201.84081 458.8049 201.65397 458.40386 201.28027 458.12585 curveto
+200.91113 457.84331 200.3802 457.70204 199.6875 457.70203 curveto
+199.30924 457.70204 198.90364 457.74305 198.4707 457.82507 curveto
+198.03776 457.90711 197.56152 458.03472 197.04199 458.20789 curveto
+197.04199 456.97742 lineto
+197.56608 456.83159 198.05599 456.72222 198.51172 456.64929 curveto
+198.972 456.57639 199.40494 456.53993 199.81055 456.53992 curveto
+200.85872 456.53993 201.68815 456.77918 202.29883 457.25769 curveto
+202.9095 457.73166 203.21484 458.37424 203.21484 459.18542 curveto
+203.21484 459.75054 203.05305 460.22905 202.72949 460.62097 curveto
+202.40592 461.00835 201.94563 461.27723 201.34863 461.42761 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+206.22266 465.19421 moveto
+207.66504 465.19421 lineto
+207.66504 466.37 lineto
+206.54395 468.5575 lineto
+205.66211 468.5575 lineto
+206.22266 466.37 lineto
+206.22266 465.19421 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+213.3252 460.15613 moveto
+212.65071 460.15613 212.11751 460.42046 211.72559 460.9491 curveto
+211.33366 461.47319 211.13769 462.19324 211.1377 463.10925 curveto
+211.13769 464.02527 211.33138 464.7476 211.71875 465.27625 curveto
+212.11067 465.80033 212.64616 466.06238 213.3252 466.06238 curveto
+213.99511 466.06238 214.52604 465.79806 214.91797 465.26941 curveto
+215.30989 464.74077 215.50585 464.02071 215.50586 463.10925 curveto
+215.50585 462.20236 215.30989 461.48458 214.91797 460.95593 curveto
+214.52604 460.42274 213.99511 460.15613 213.3252 460.15613 curveto
+213.3252 459.08972 moveto
+214.41894 459.08973 215.27799 459.4452 215.90234 460.15613 curveto
+216.52669 460.86707 216.83886 461.85145 216.83887 463.10925 curveto
+216.83886 464.36251 216.52669 465.34688 215.90234 466.06238 curveto
+215.27799 466.77332 214.41894 467.12878 213.3252 467.12878 curveto
+212.22688 467.12878 211.36556 466.77332 210.74121 466.06238 curveto
+210.12142 465.34688 209.81152 464.36251 209.81152 463.10925 curveto
+209.81152 461.85145 210.12142 460.86707 210.74121 460.15613 curveto
+211.36556 459.4452 212.22688 459.08973 213.3252 459.08972 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+218.71875 456.3075 moveto
+219.8125 456.3075 lineto
+220.49609 457.38303 221.00651 458.43576 221.34375 459.4657 curveto
+221.68554 460.49565 221.85644 461.51876 221.85645 462.53503 curveto
+221.85644 463.55587 221.68554 464.58354 221.34375 465.61804 curveto
+221.00651 466.65255 220.49609 467.70528 219.8125 468.77625 curveto
+218.71875 468.77625 lineto
+219.32487 467.73262 219.77604 466.69584 220.07227 465.66589 curveto
+220.37304 464.63139 220.52343 463.58777 220.52344 462.53503 curveto
+220.52343 461.48231 220.37304 460.44324 220.07227 459.41785 curveto
+219.77604 458.39246 219.32487 457.35568 218.71875 456.3075 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+228.20898 455.77429 moveto
+227.5983 456.82248 227.14485 457.85926 226.84863 458.88464 curveto
+226.55241 459.91004 226.40429 460.9491 226.4043 462.00183 curveto
+226.40429 463.05457 226.55241 464.09819 226.84863 465.13269 curveto
+227.14941 466.16264 227.60286 467.19942 228.20898 468.24304 curveto
+227.11523 468.24304 lineto
+226.43164 467.17208 225.91894 466.11934 225.57715 465.08484 curveto
+225.23991 464.05034 225.07129 463.02267 225.07129 462.00183 curveto
+225.07129 460.98556 225.23991 459.96245 225.57715 458.9325 curveto
+225.91439 457.90256 226.42708 456.84982 227.11523 455.77429 curveto
+228.20898 455.77429 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+233.95801 460.74402 moveto
+233.33821 460.74402 232.84603 460.95594 232.48145 461.37976 curveto
+232.12142 461.80359 231.9414 462.38465 231.94141 463.12292 curveto
+231.9414 463.85665 232.12142 464.43771 232.48145 464.86609 curveto
+232.84603 465.28992 233.33821 465.50183 233.95801 465.50183 curveto
+234.57779 465.50183 235.0677 465.28992 235.42773 464.86609 curveto
+235.79231 464.43771 235.9746 463.85665 235.97461 463.12292 curveto
+235.9746 462.38465 235.79231 461.80359 235.42773 461.37976 curveto
+235.0677 460.95594 234.57779 460.74402 233.95801 460.74402 curveto
+236.69922 456.41687 moveto
+236.69922 457.67468 lineto
+236.35286 457.51063 236.00195 457.3853 235.64648 457.29871 curveto
+235.29557 457.21213 234.94693 457.16883 234.60059 457.16882 curveto
+233.68912 457.16883 232.99186 457.47645 232.50879 458.09167 curveto
+232.03027 458.70692 231.75683 459.6366 231.68848 460.88074 curveto
+231.95735 460.48426 232.29459 460.1812 232.7002 459.97156 curveto
+233.10579 459.75737 233.5524 459.65028 234.04004 459.65027 curveto
+235.06542 459.65028 235.87434 459.96245 236.4668 460.58679 curveto
+237.06379 461.20659 237.3623 462.05197 237.3623 463.12292 curveto
+237.3623 464.1711 237.0524 465.01192 236.43262 465.64539 curveto
+235.81282 466.27885 234.98795 466.59558 233.95801 466.59558 curveto
+232.77767 466.59558 231.87532 466.14441 231.25098 465.24207 curveto
+230.62663 464.33517 230.31445 463.02267 230.31445 461.30457 curveto
+230.31445 459.69129 230.69726 458.40614 231.46289 457.4491 curveto
+232.22851 456.48752 233.25618 456.00672 234.5459 456.00671 curveto
+234.89225 456.00672 235.24088 456.0409 235.5918 456.10925 curveto
+235.94726 456.17762 236.3164 456.28016 236.69922 456.41687 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+239.8916 464.66101 moveto
+241.33398 464.66101 lineto
+241.33398 465.83679 lineto
+240.21289 468.02429 lineto
+239.33105 468.02429 lineto
+239.8916 465.83679 lineto
+239.8916 464.66101 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+247.99902 457.39441 moveto
+244.5127 462.84265 lineto
+247.99902 462.84265 lineto
+247.99902 457.39441 lineto
+247.63672 456.19128 moveto
+249.37305 456.19128 lineto
+249.37305 462.84265 lineto
+250.8291 462.84265 lineto
+250.8291 463.99109 lineto
+249.37305 463.99109 lineto
+249.37305 466.39734 lineto
+247.99902 466.39734 lineto
+247.99902 463.99109 lineto
+243.3916 463.99109 lineto
+243.3916 462.65808 lineto
+247.63672 456.19128 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+253.2627 464.66101 moveto
+254.70508 464.66101 lineto
+254.70508 465.83679 lineto
+253.58398 468.02429 lineto
+252.70215 468.02429 lineto
+253.2627 465.83679 lineto
+253.2627 464.66101 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+262.43652 462.48035 moveto
+262.43652 461.56889 262.24739 460.86251 261.86914 460.36121 curveto
+261.49544 459.85991 260.96907 459.60926 260.29004 459.60925 curveto
+259.61556 459.60926 259.08919 459.85991 258.71094 460.36121 curveto
+258.33724 460.86251 258.15039 461.56889 258.15039 462.48035 curveto
+258.15039 463.38725 258.33724 464.09135 258.71094 464.59265 curveto
+259.08919 465.09395 259.61556 465.34461 260.29004 465.3446 curveto
+260.96907 465.34461 261.49544 465.09395 261.86914 464.59265 curveto
+262.24739 464.09135 262.43652 463.38725 262.43652 462.48035 curveto
+263.69434 465.44714 moveto
+263.69433 466.75053 263.40494 467.71895 262.82617 468.35242 curveto
+262.24739 468.99044 261.361 469.30945 260.16699 469.30945 curveto
+259.72493 469.30945 259.30794 469.27527 258.91602 469.20691 curveto
+258.52409 469.1431 258.14355 469.04284 257.77441 468.90613 curveto
+257.77441 467.6825 lineto
+258.14355 467.88301 258.50814 468.03113 258.86816 468.12683 curveto
+259.22819 468.22253 259.59505 468.27038 259.96875 468.27039 curveto
+260.79362 468.27038 261.41113 468.05391 261.82129 467.62097 curveto
+262.23144 467.19259 262.43652 466.54317 262.43652 465.67273 curveto
+262.43652 465.05066 lineto
+262.17675 465.50183 261.84407 465.83907 261.43848 466.06238 curveto
+261.03287 466.28569 260.54752 466.39734 259.98242 466.39734 curveto
+259.04362 466.39734 258.28711 466.03959 257.71289 465.3241 curveto
+257.13867 464.6086 256.85156 463.66069 256.85156 462.48035 curveto
+256.85156 461.29546 257.13867 460.34526 257.71289 459.62976 curveto
+258.28711 458.91427 259.04362 458.55653 259.98242 458.55652 curveto
+260.54752 458.55653 261.03287 458.66818 261.43848 458.89148 curveto
+261.84407 459.11479 262.17675 459.45203 262.43652 459.9032 curveto
+262.43652 458.74109 lineto
+263.69434 458.74109 lineto
+263.69434 465.44714 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+266.08691 455.77429 moveto
+267.18066 455.77429 lineto
+267.86425 456.84982 268.37467 457.90256 268.71191 458.9325 curveto
+269.05371 459.96245 269.22461 460.98556 269.22461 462.00183 curveto
+269.22461 463.02267 269.05371 464.05034 268.71191 465.08484 curveto
+268.37467 466.11934 267.86425 467.17208 267.18066 468.24304 curveto
+266.08691 468.24304 lineto
+266.69303 467.19942 267.1442 466.16264 267.44043 465.13269 curveto
+267.74121 464.09819 267.8916 463.05457 267.8916 462.00183 curveto
+267.8916 460.9491 267.74121 459.91004 267.44043 458.88464 curveto
+267.1442 457.85926 266.69303 456.82248 266.08691 455.77429 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+275.57715 455.77429 moveto
+274.96647 456.82248 274.51302 457.85926 274.2168 458.88464 curveto
+273.92057 459.91004 273.77246 460.9491 273.77246 462.00183 curveto
+273.77246 463.05457 273.92057 464.09819 274.2168 465.13269 curveto
+274.51757 466.16264 274.97102 467.19942 275.57715 468.24304 curveto
+274.4834 468.24304 lineto
+273.7998 467.17208 273.28711 466.11934 272.94531 465.08484 curveto
+272.60807 464.05034 272.43945 463.02267 272.43945 462.00183 curveto
+272.43945 460.98556 272.60807 459.96245 272.94531 458.9325 curveto
+273.28255 457.90256 273.79524 456.84982 274.4834 455.77429 curveto
+275.57715 455.77429 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+281.15527 461.55066 moveto
+280.49902 461.55066 279.98177 461.72612 279.60352 462.07703 curveto
+279.22982 462.42794 279.04297 462.91101 279.04297 463.52625 curveto
+279.04297 464.14148 279.22982 464.62455 279.60352 464.97546 curveto
+279.98177 465.32638 280.49902 465.50183 281.15527 465.50183 curveto
+281.81152 465.50183 282.32877 465.32638 282.70703 464.97546 curveto
+283.08528 464.62 283.27441 464.13692 283.27441 463.52625 curveto
+283.27441 462.91101 283.08528 462.42794 282.70703 462.07703 curveto
+282.33333 461.72612 281.81608 461.55066 281.15527 461.55066 curveto
+279.77441 460.96277 moveto
+279.18196 460.81694 278.7194 460.54122 278.38672 460.13562 curveto
+278.05859 459.73003 277.89453 459.23556 277.89453 458.65222 curveto
+277.89453 457.83648 278.18392 457.19162 278.7627 456.71765 curveto
+279.34603 456.2437 280.14355 456.00672 281.15527 456.00671 curveto
+282.17154 456.00672 282.96907 456.2437 283.54785 456.71765 curveto
+284.12662 457.19162 284.41601 457.83648 284.41602 458.65222 curveto
+284.41601 459.23556 284.24967 459.73003 283.91699 460.13562 curveto
+283.58886 460.54122 283.13085 460.81694 282.54297 460.96277 curveto
+283.20833 461.11772 283.72558 461.42078 284.09473 461.87195 curveto
+284.46842 462.32312 284.65527 462.87456 284.65527 463.52625 curveto
+284.65527 464.51518 284.35221 465.27397 283.74609 465.80261 curveto
+283.14452 466.33126 282.28092 466.59558 281.15527 466.59558 curveto
+280.02962 466.59558 279.16373 466.33126 278.55762 465.80261 curveto
+277.95605 465.27397 277.65527 464.51518 277.65527 463.52625 curveto
+277.65527 462.87456 277.84212 462.32312 278.21582 461.87195 curveto
+278.58952 461.42078 279.10905 461.11772 279.77441 460.96277 curveto
+279.26855 458.7821 moveto
+279.26855 459.31076 279.43261 459.72319 279.76074 460.01941 curveto
+280.09342 460.31564 280.55826 460.46375 281.15527 460.46375 curveto
+281.74772 460.46375 282.21028 460.31564 282.54297 460.01941 curveto
+282.8802 459.72319 283.04882 459.31076 283.04883 458.7821 curveto
+283.04882 458.25347 282.8802 457.84103 282.54297 457.5448 curveto
+282.21028 457.24858 281.74772 457.10047 281.15527 457.10046 curveto
+280.55826 457.10047 280.09342 457.24858 279.76074 457.5448 curveto
+279.43261 457.84103 279.26855 458.25347 279.26855 458.7821 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+287.25977 464.66101 moveto
+288.70215 464.66101 lineto
+288.70215 465.83679 lineto
+287.58105 468.02429 lineto
+286.69922 468.02429 lineto
+287.25977 465.83679 lineto
+287.25977 464.66101 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+291.58691 456.19128 moveto
+297.00781 456.19128 lineto
+297.00781 457.35339 lineto
+292.85156 457.35339 lineto
+292.85156 459.85535 lineto
+293.05208 459.78699 293.2526 459.73686 293.45312 459.70496 curveto
+293.65364 459.6685 293.85416 459.65028 294.05469 459.65027 curveto
+295.19401 459.65028 296.09635 459.96245 296.76172 460.58679 curveto
+297.42708 461.21115 297.75976 462.05652 297.75977 463.12292 curveto
+297.75976 464.22123 297.41796 465.07573 296.73438 465.6864 curveto
+296.05078 466.29252 295.08691 466.59558 293.84277 466.59558 curveto
+293.41438 466.59558 292.97689 466.55912 292.53027 466.48621 curveto
+292.08821 466.41329 291.63021 466.30391 291.15625 466.15808 curveto
+291.15625 464.77039 lineto
+291.5664 464.99369 291.99023 465.16004 292.42773 465.26941 curveto
+292.86523 465.37879 293.3278 465.43347 293.81543 465.43347 curveto
+294.60384 465.43347 295.22818 465.22612 295.68848 464.8114 curveto
+296.14876 464.39669 296.3789 463.83386 296.37891 463.12292 curveto
+296.3789 462.41199 296.14876 461.84917 295.68848 461.43445 curveto
+295.22818 461.01974 294.60384 460.81238 293.81543 460.81238 curveto
+293.44629 460.81238 293.07715 460.8534 292.70801 460.93542 curveto
+292.34342 461.01746 291.96972 461.14507 291.58691 461.31824 curveto
+291.58691 456.19128 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+300.63086 464.66101 moveto
+302.07324 464.66101 lineto
+302.07324 465.83679 lineto
+300.95215 468.02429 lineto
+300.07031 468.02429 lineto
+300.63086 465.83679 lineto
+300.63086 464.66101 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+309.80469 462.48035 moveto
+309.80468 461.56889 309.61555 460.86251 309.2373 460.36121 curveto
+308.8636 459.85991 308.33723 459.60926 307.6582 459.60925 curveto
+306.98372 459.60926 306.45735 459.85991 306.0791 460.36121 curveto
+305.7054 460.86251 305.51855 461.56889 305.51855 462.48035 curveto
+305.51855 463.38725 305.7054 464.09135 306.0791 464.59265 curveto
+306.45735 465.09395 306.98372 465.34461 307.6582 465.3446 curveto
+308.33723 465.34461 308.8636 465.09395 309.2373 464.59265 curveto
+309.61555 464.09135 309.80468 463.38725 309.80469 462.48035 curveto
+311.0625 465.44714 moveto
+311.06249 466.75053 310.7731 467.71895 310.19434 468.35242 curveto
+309.61555 468.99044 308.72916 469.30945 307.53516 469.30945 curveto
+307.0931 469.30945 306.6761 469.27527 306.28418 469.20691 curveto
+305.89225 469.1431 305.51172 469.04284 305.14258 468.90613 curveto
+305.14258 467.6825 lineto
+305.51172 467.88301 305.8763 468.03113 306.23633 468.12683 curveto
+306.59635 468.22253 306.96321 468.27038 307.33691 468.27039 curveto
+308.16178 468.27038 308.77929 468.05391 309.18945 467.62097 curveto
+309.5996 467.19259 309.80468 466.54317 309.80469 465.67273 curveto
+309.80469 465.05066 lineto
+309.54492 465.50183 309.21223 465.83907 308.80664 466.06238 curveto
+308.40104 466.28569 307.91569 466.39734 307.35059 466.39734 curveto
+306.41178 466.39734 305.65527 466.03959 305.08105 465.3241 curveto
+304.50683 464.6086 304.21973 463.66069 304.21973 462.48035 curveto
+304.21973 461.29546 304.50683 460.34526 305.08105 459.62976 curveto
+305.65527 458.91427 306.41178 458.55653 307.35059 458.55652 curveto
+307.91569 458.55653 308.40104 458.66818 308.80664 458.89148 curveto
+309.21223 459.11479 309.54492 459.45203 309.80469 459.9032 curveto
+309.80469 458.74109 lineto
+311.0625 458.74109 lineto
+311.0625 465.44714 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+313.45508 455.77429 moveto
+314.54883 455.77429 lineto
+315.23242 456.84982 315.74284 457.90256 316.08008 458.9325 curveto
+316.42187 459.96245 316.59277 460.98556 316.59277 462.00183 curveto
+316.59277 463.02267 316.42187 464.05034 316.08008 465.08484 curveto
+315.74284 466.11934 315.23242 467.17208 314.54883 468.24304 curveto
+313.45508 468.24304 lineto
+314.0612 467.19942 314.51237 466.16264 314.80859 465.13269 curveto
+315.10937 464.09819 315.25976 463.05457 315.25977 462.00183 curveto
+315.25976 460.9491 315.10937 459.91004 314.80859 458.88464 curveto
+314.51237 457.85926 314.0612 456.82248 313.45508 455.77429 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+174.3125 475.84265 moveto
+173.70182 476.89084 173.24837 477.92762 172.95215 478.953 curveto
+172.65592 479.9784 172.50781 481.01746 172.50781 482.07019 curveto
+172.50781 483.12293 172.65592 484.16655 172.95215 485.20105 curveto
+173.25293 486.231 173.70638 487.26778 174.3125 488.3114 curveto
+173.21875 488.3114 lineto
+172.53515 487.24044 172.02246 486.1877 171.68066 485.1532 curveto
+171.34342 484.1187 171.1748 483.09103 171.1748 482.07019 curveto
+171.1748 481.05392 171.34342 480.03081 171.68066 479.00085 curveto
+172.0179 477.97092 172.5306 476.91818 173.21875 475.84265 curveto
+174.3125 475.84265 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+176.97852 486.25378 moveto
+176.97852 484.99597 lineto
+177.32487 485.16004 177.67578 485.28536 178.03125 485.37195 curveto
+178.38672 485.45854 178.73535 485.50183 179.07715 485.50183 curveto
+179.9886 485.50183 180.68359 485.19649 181.16211 484.58582 curveto
+181.64518 483.97058 181.92089 483.03862 181.98926 481.78992 curveto
+181.72493 482.18185 181.38997 482.48263 180.98438 482.69226 curveto
+180.57877 482.9019 180.12988 483.00672 179.6377 483.00671 curveto
+178.61686 483.00672 177.80794 482.6991 177.21094 482.08386 curveto
+176.61849 481.46408 176.32226 480.6187 176.32227 479.54773 curveto
+176.32226 478.49956 176.63216 477.65874 177.25195 477.02527 curveto
+177.87174 476.39182 178.69661 476.07508 179.72656 476.07507 curveto
+180.9069 476.07508 181.80696 476.52853 182.42676 477.43542 curveto
+183.0511 478.33778 183.36327 479.65028 183.36328 481.37292 curveto
+183.36327 482.98165 182.98046 484.26681 182.21484 485.22839 curveto
+181.45377 486.18543 180.42838 486.66394 179.13867 486.66394 curveto
+178.79231 486.66394 178.4414 486.62976 178.08594 486.5614 curveto
+177.73047 486.49304 177.36133 486.3905 176.97852 486.25378 curveto
+179.72656 481.92664 moveto
+180.34635 481.92664 180.83626 481.71473 181.19629 481.29089 curveto
+181.56087 480.86707 181.74316 480.28602 181.74316 479.54773 curveto
+181.74316 478.81401 181.56087 478.23524 181.19629 477.8114 curveto
+180.83626 477.38303 180.34635 477.16883 179.72656 477.16882 curveto
+179.10677 477.16883 178.61458 477.38303 178.25 477.8114 curveto
+177.88997 478.23524 177.70996 478.81401 177.70996 479.54773 curveto
+177.70996 480.28602 177.88997 480.86707 178.25 481.29089 curveto
+178.61458 481.71473 179.10677 481.92664 179.72656 481.92664 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+185.99512 484.72937 moveto
+187.4375 484.72937 lineto
+187.4375 485.90515 lineto
+186.31641 488.09265 lineto
+185.43457 488.09265 lineto
+185.99512 485.90515 lineto
+185.99512 484.72937 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+193.43262 480.81238 moveto
+192.81282 480.81238 192.32063 481.0243 191.95605 481.44812 curveto
+191.59603 481.87195 191.41601 482.45301 191.41602 483.19128 curveto
+191.41601 483.92501 191.59603 484.50606 191.95605 484.93445 curveto
+192.32063 485.35828 192.81282 485.57019 193.43262 485.57019 curveto
+194.0524 485.57019 194.54231 485.35828 194.90234 484.93445 curveto
+195.26692 484.50606 195.44921 483.92501 195.44922 483.19128 curveto
+195.44921 482.45301 195.26692 481.87195 194.90234 481.44812 curveto
+194.54231 481.0243 194.0524 480.81238 193.43262 480.81238 curveto
+196.17383 476.48523 moveto
+196.17383 477.74304 lineto
+195.82747 477.57899 195.47656 477.45366 195.12109 477.36707 curveto
+194.77018 477.28049 194.42154 477.23719 194.0752 477.23718 curveto
+193.16373 477.23719 192.46647 477.54481 191.9834 478.16003 curveto
+191.50488 478.77528 191.23144 479.70496 191.16309 480.9491 curveto
+191.43196 480.55262 191.7692 480.24956 192.1748 480.03992 curveto
+192.5804 479.82573 193.02701 479.71863 193.51465 479.71863 curveto
+194.54003 479.71863 195.34895 480.03081 195.94141 480.65515 curveto
+196.5384 481.27495 196.83691 482.12032 196.83691 483.19128 curveto
+196.83691 484.23946 196.52701 485.08028 195.90723 485.71375 curveto
+195.28743 486.34721 194.46256 486.66394 193.43262 486.66394 curveto
+192.25228 486.66394 191.34993 486.21277 190.72559 485.31042 curveto
+190.10124 484.40353 189.78906 483.09103 189.78906 481.37292 curveto
+189.78906 479.75965 190.17187 478.4745 190.9375 477.51746 curveto
+191.70312 476.55588 192.73079 476.07508 194.02051 476.07507 curveto
+194.36686 476.07508 194.71549 476.10926 195.06641 476.17761 curveto
+195.42187 476.24598 195.79101 476.34852 196.17383 476.48523 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+199.36621 484.72937 moveto
+200.80859 484.72937 lineto
+200.80859 485.90515 lineto
+199.6875 488.09265 lineto
+198.80566 488.09265 lineto
+199.36621 485.90515 lineto
+199.36621 484.72937 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+206.46875 479.69128 moveto
+205.79427 479.69129 205.26106 479.95561 204.86914 480.48425 curveto
+204.47721 481.00835 204.28125 481.7284 204.28125 482.64441 curveto
+204.28125 483.56043 204.47493 484.28276 204.8623 484.8114 curveto
+205.25423 485.33549 205.78971 485.59754 206.46875 485.59753 curveto
+207.13867 485.59754 207.66959 485.33321 208.06152 484.80457 curveto
+208.45344 484.27592 208.64941 483.55587 208.64941 482.64441 curveto
+208.64941 481.73751 208.45344 481.01974 208.06152 480.49109 curveto
+207.66959 479.95789 207.13867 479.69129 206.46875 479.69128 curveto
+206.46875 478.62488 moveto
+207.56249 478.62489 208.42154 478.98035 209.0459 479.69128 curveto
+209.67024 480.40223 209.98241 481.3866 209.98242 482.64441 curveto
+209.98241 483.89767 209.67024 484.88204 209.0459 485.59753 curveto
+208.42154 486.30847 207.56249 486.66394 206.46875 486.66394 curveto
+205.37044 486.66394 204.50911 486.30847 203.88477 485.59753 curveto
+203.26497 484.88204 202.95508 483.89767 202.95508 482.64441 curveto
+202.95508 481.3866 203.26497 480.40223 203.88477 479.69128 curveto
+204.50911 478.98035 205.37044 478.62489 206.46875 478.62488 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+211.8623 475.84265 moveto
+212.95605 475.84265 lineto
+213.63965 476.91818 214.15006 477.97092 214.4873 479.00085 curveto
+214.8291 480.03081 215 481.05392 215 482.07019 curveto
+215 483.09103 214.8291 484.1187 214.4873 485.1532 curveto
+214.15006 486.1877 213.63965 487.24044 212.95605 488.3114 curveto
+211.8623 488.3114 lineto
+212.46842 487.26778 212.91959 486.231 213.21582 485.20105 curveto
+213.5166 484.16655 213.66699 483.12293 213.66699 482.07019 curveto
+213.66699 481.01746 213.5166 479.9784 213.21582 478.953 curveto
+212.91959 477.92762 212.46842 476.89084 211.8623 475.84265 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+222.12305 476.34265 moveto
+221.51237 477.39084 221.05892 478.42762 220.7627 479.453 curveto
+220.46647 480.4784 220.31836 481.51746 220.31836 482.57019 curveto
+220.31836 483.62293 220.46647 484.66655 220.7627 485.70105 curveto
+221.06347 486.731 221.51692 487.76778 222.12305 488.8114 curveto
+221.0293 488.8114 lineto
+220.3457 487.74044 219.83301 486.6877 219.49121 485.6532 curveto
+219.15397 484.6187 218.98535 483.59103 218.98535 482.57019 curveto
+218.98535 481.55392 219.15397 480.53081 219.49121 479.50085 curveto
+219.82845 478.47092 220.34114 477.41818 221.0293 476.34265 curveto
+222.12305 476.34265 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+224.9873 485.80359 moveto
+227.24316 485.80359 lineto
+227.24316 478.01746 lineto
+224.78906 478.50964 lineto
+224.78906 477.25183 lineto
+227.22949 476.75964 lineto
+228.61035 476.75964 lineto
+228.61035 485.80359 lineto
+230.86621 485.80359 lineto
+230.86621 486.9657 lineto
+224.9873 486.9657 lineto
+224.9873 485.80359 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+236.61523 477.66882 moveto
+235.90429 477.66883 235.36881 478.01974 235.00879 478.72156 curveto
+234.65332 479.41883 234.47558 480.46929 234.47559 481.87292 curveto
+234.47558 483.27202 234.65332 484.32247 235.00879 485.02429 curveto
+235.36881 485.72156 235.90429 486.07019 236.61523 486.07019 curveto
+237.33072 486.07019 237.86621 485.72156 238.22168 485.02429 curveto
+238.5817 484.32247 238.76171 483.27202 238.76172 481.87292 curveto
+238.76171 480.46929 238.5817 479.41883 238.22168 478.72156 curveto
+237.86621 478.01974 237.33072 477.66883 236.61523 477.66882 curveto
+236.61523 476.57507 moveto
+237.75911 476.57508 238.63183 477.02853 239.2334 477.93542 curveto
+239.83951 478.83778 240.14257 480.15028 240.14258 481.87292 curveto
+240.14257 483.59103 239.83951 484.90353 239.2334 485.81042 curveto
+238.63183 486.71277 237.75911 487.16394 236.61523 487.16394 curveto
+235.47135 487.16394 234.59635 486.71277 233.99023 485.81042 curveto
+233.38867 484.90353 233.08789 483.59103 233.08789 481.87292 curveto
+233.08789 480.15028 233.38867 478.83778 233.99023 477.93542 curveto
+234.59635 477.02853 235.47135 476.57508 236.61523 476.57507 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+242.71973 485.22937 moveto
+244.16211 485.22937 lineto
+244.16211 486.40515 lineto
+243.04102 488.59265 lineto
+242.15918 488.59265 lineto
+242.71973 486.40515 lineto
+242.71973 485.22937 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+246.68457 476.75964 moveto
+253.24707 476.75964 lineto
+253.24707 477.34753 lineto
+249.54199 486.9657 lineto
+248.09961 486.9657 lineto
+251.58594 477.92175 lineto
+246.68457 477.92175 lineto
+246.68457 476.75964 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+256.09082 485.22937 moveto
+257.5332 485.22937 lineto
+257.5332 486.40515 lineto
+256.41211 488.59265 lineto
+255.53027 488.59265 lineto
+256.09082 486.40515 lineto
+256.09082 485.22937 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+263.19336 480.19128 moveto
+262.51888 480.19129 261.98567 480.45561 261.59375 480.98425 curveto
+261.20182 481.50835 261.00586 482.2284 261.00586 483.14441 curveto
+261.00586 484.06043 261.19954 484.78276 261.58691 485.3114 curveto
+261.97884 485.83549 262.51432 486.09754 263.19336 486.09753 curveto
+263.86328 486.09754 264.3942 485.83321 264.78613 485.30457 curveto
+265.17805 484.77592 265.37402 484.05587 265.37402 483.14441 curveto
+265.37402 482.23751 265.17805 481.51974 264.78613 480.99109 curveto
+264.3942 480.45789 263.86328 480.19129 263.19336 480.19128 curveto
+263.19336 479.12488 moveto
+264.2871 479.12489 265.14615 479.48035 265.77051 480.19128 curveto
+266.39485 480.90223 266.70702 481.8866 266.70703 483.14441 curveto
+266.70702 484.39767 266.39485 485.38204 265.77051 486.09753 curveto
+265.14615 486.80847 264.2871 487.16394 263.19336 487.16394 curveto
+262.09505 487.16394 261.23372 486.80847 260.60938 486.09753 curveto
+259.98958 485.38204 259.67969 484.39767 259.67969 483.14441 curveto
+259.67969 481.8866 259.98958 480.90223 260.60938 480.19128 curveto
+261.23372 479.48035 262.09505 479.12489 263.19336 479.12488 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+268.58691 476.34265 moveto
+269.68066 476.34265 lineto
+270.36425 477.41818 270.87467 478.47092 271.21191 479.50085 curveto
+271.55371 480.53081 271.72461 481.55392 271.72461 482.57019 curveto
+271.72461 483.59103 271.55371 484.6187 271.21191 485.6532 curveto
+270.87467 486.6877 270.36425 487.74044 269.68066 488.8114 curveto
+268.58691 488.8114 lineto
+269.19303 487.76778 269.6442 486.731 269.94043 485.70105 curveto
+270.24121 484.66655 270.3916 483.62293 270.3916 482.57019 curveto
+270.3916 481.51746 270.24121 480.4784 269.94043 479.453 curveto
+269.6442 478.42762 269.19303 477.39084 268.58691 476.34265 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+276.49121 476.34265 moveto
+275.88053 477.39084 275.42708 478.42762 275.13086 479.453 curveto
+274.83463 480.4784 274.68652 481.51746 274.68652 482.57019 curveto
+274.68652 483.62293 274.83463 484.66655 275.13086 485.70105 curveto
+275.43164 486.731 275.88509 487.76778 276.49121 488.8114 curveto
+275.39746 488.8114 lineto
+274.71386 487.74044 274.20117 486.6877 273.85938 485.6532 curveto
+273.52213 484.6187 273.35351 483.59103 273.35352 482.57019 curveto
+273.35351 481.55392 273.52213 480.53081 273.85938 479.50085 curveto
+274.19661 478.47092 274.70931 477.41818 275.39746 476.34265 curveto
+276.49121 476.34265 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+279.35547 485.80359 moveto
+281.61133 485.80359 lineto
+281.61133 478.01746 lineto
+279.15723 478.50964 lineto
+279.15723 477.25183 lineto
+281.59766 476.75964 lineto
+282.97852 476.75964 lineto
+282.97852 485.80359 lineto
+285.23438 485.80359 lineto
+285.23438 486.9657 lineto
+279.35547 486.9657 lineto
+279.35547 485.80359 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+288.26953 485.80359 moveto
+290.52539 485.80359 lineto
+290.52539 478.01746 lineto
+288.07129 478.50964 lineto
+288.07129 477.25183 lineto
+290.51172 476.75964 lineto
+291.89258 476.75964 lineto
+291.89258 485.80359 lineto
+294.14844 485.80359 lineto
+294.14844 486.9657 lineto
+288.26953 486.9657 lineto
+288.26953 485.80359 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+297.08789 485.22937 moveto
+298.53027 485.22937 lineto
+298.53027 486.40515 lineto
+297.40918 488.59265 lineto
+296.52734 488.59265 lineto
+297.08789 486.40515 lineto
+297.08789 485.22937 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+304.35449 482.11902 moveto
+303.69824 482.11902 303.18099 482.29448 302.80273 482.64539 curveto
+302.42903 482.9963 302.24219 483.47937 302.24219 484.0946 curveto
+302.24219 484.70984 302.42903 485.19291 302.80273 485.54382 curveto
+303.18099 485.89474 303.69824 486.07019 304.35449 486.07019 curveto
+305.01074 486.07019 305.52799 485.89474 305.90625 485.54382 curveto
+306.2845 485.18836 306.47363 484.70528 306.47363 484.0946 curveto
+306.47363 483.47937 306.2845 482.9963 305.90625 482.64539 curveto
+305.53255 482.29448 305.01529 482.11902 304.35449 482.11902 curveto
+302.97363 481.53113 moveto
+302.38118 481.3853 301.91862 481.10958 301.58594 480.70398 curveto
+301.25781 480.29839 301.09375 479.80392 301.09375 479.22058 curveto
+301.09375 478.40483 301.38314 477.75998 301.96191 477.28601 curveto
+302.54524 476.81206 303.34277 476.57508 304.35449 476.57507 curveto
+305.37076 476.57508 306.16829 476.81206 306.74707 477.28601 curveto
+307.32584 477.75998 307.61523 478.40483 307.61523 479.22058 curveto
+307.61523 479.80392 307.44889 480.29839 307.11621 480.70398 curveto
+306.78808 481.10958 306.33007 481.3853 305.74219 481.53113 curveto
+306.40755 481.68608 306.9248 481.98914 307.29395 482.44031 curveto
+307.66764 482.89148 307.85448 483.44292 307.85449 484.0946 curveto
+307.85448 485.08354 307.55142 485.84233 306.94531 486.37097 curveto
+306.34374 486.89962 305.48014 487.16394 304.35449 487.16394 curveto
+303.22884 487.16394 302.36295 486.89962 301.75684 486.37097 curveto
+301.15527 485.84233 300.85449 485.08354 300.85449 484.0946 curveto
+300.85449 483.44292 301.04134 482.89148 301.41504 482.44031 curveto
+301.78874 481.98914 302.30827 481.68608 302.97363 481.53113 curveto
+302.46777 479.35046 moveto
+302.46777 479.87912 302.63183 480.29155 302.95996 480.58777 curveto
+303.29264 480.884 303.75748 481.03211 304.35449 481.0321 curveto
+304.94694 481.03211 305.4095 480.884 305.74219 480.58777 curveto
+306.07942 480.29155 306.24804 479.87912 306.24805 479.35046 curveto
+306.24804 478.82183 306.07942 478.40939 305.74219 478.11316 curveto
+305.4095 477.81694 304.94694 477.66883 304.35449 477.66882 curveto
+303.75748 477.66883 303.29264 477.81694 302.95996 478.11316 curveto
+302.63183 478.40939 302.46777 478.82183 302.46777 479.35046 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+310.45898 485.22937 moveto
+311.90137 485.22937 lineto
+311.90137 486.40515 lineto
+310.78027 488.59265 lineto
+309.89844 488.59265 lineto
+310.45898 486.40515 lineto
+310.45898 485.22937 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+317.56152 480.19128 moveto
+316.88704 480.19129 316.35384 480.45561 315.96191 480.98425 curveto
+315.56998 481.50835 315.37402 482.2284 315.37402 483.14441 curveto
+315.37402 484.06043 315.56771 484.78276 315.95508 485.3114 curveto
+316.347 485.83549 316.88248 486.09754 317.56152 486.09753 curveto
+318.23144 486.09754 318.76236 485.83321 319.1543 485.30457 curveto
+319.54622 484.77592 319.74218 484.05587 319.74219 483.14441 curveto
+319.74218 482.23751 319.54622 481.51974 319.1543 480.99109 curveto
+318.76236 480.45789 318.23144 480.19129 317.56152 480.19128 curveto
+317.56152 479.12488 moveto
+318.65527 479.12489 319.51432 479.48035 320.13867 480.19128 curveto
+320.76301 480.90223 321.07519 481.8866 321.0752 483.14441 curveto
+321.07519 484.39767 320.76301 485.38204 320.13867 486.09753 curveto
+319.51432 486.80847 318.65527 487.16394 317.56152 487.16394 curveto
+316.46321 487.16394 315.60189 486.80847 314.97754 486.09753 curveto
+314.35775 485.38204 314.04785 484.39767 314.04785 483.14441 curveto
+314.04785 481.8866 314.35775 480.90223 314.97754 480.19128 curveto
+315.60189 479.48035 316.46321 479.12489 317.56152 479.12488 curveto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+322.95508 476.34265 moveto
+324.04883 476.34265 lineto
+324.73242 477.41818 325.24284 478.47092 325.58008 479.50085 curveto
+325.92187 480.53081 326.09277 481.55392 326.09277 482.57019 curveto
+326.09277 483.59103 325.92187 484.6187 325.58008 485.6532 curveto
+325.24284 486.6877 324.73242 487.74044 324.04883 488.8114 curveto
+322.95508 488.8114 lineto
+323.5612 487.76778 324.01237 486.731 324.30859 485.70105 curveto
+324.60937 484.66655 324.75976 483.62293 324.75977 482.57019 curveto
+324.75976 481.51746 324.60937 480.4784 324.30859 479.453 curveto
+324.01237 478.42762 323.5612 477.39084 322.95508 476.34265 curveto
+fill
+grestore
+gsave [1.436848 0 0 0.806571 118.9493 72.56034] concat
+0 0 0 setrgbcolor
+[] 0 setdash
+1.5 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+154.5 482.61218 moveto
+154.5 515.59418 125.716 542.36218 90.25 542.36218 curveto
+54.784 542.36218 26 515.59418 26 482.61218 curveto
+26 449.63018 54.784 422.86218 90.25 422.86218 curveto
+125.716 422.86218 154.5 449.63018 154.5 482.61218 curveto
+closepath
+stroke
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+244.37402 420.15613 moveto
+245.75488 420.15613 lineto
+245.75488 430.36218 lineto
+244.37402 430.36218 lineto
+244.37402 420.15613 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+249.69238 420.5321 moveto
+249.69238 422.70593 lineto
+252.2832 422.70593 lineto
+252.2832 423.68347 lineto
+249.69238 423.68347 lineto
+249.69238 427.83972 lineto
+249.69238 428.46407 249.77669 428.86511 249.94531 429.04285 curveto
+250.11849 429.22058 250.46712 429.30945 250.99121 429.30945 curveto
+252.2832 429.30945 lineto
+252.2832 430.36218 lineto
+250.99121 430.36218 lineto
+250.0205 430.36218 249.35058 430.18217 248.98145 429.82214 curveto
+248.6123 429.45756 248.42773 428.79675 248.42773 427.83972 curveto
+248.42773 423.68347 lineto
+247.50488 423.68347 lineto
+247.50488 422.70593 lineto
+248.42773 422.70593 lineto
+248.42773 420.5321 lineto
+249.69238 420.5321 lineto
+fill
+grestore
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+250.25488 525.79089 moveto
+250.25488 529.62585 lineto
+251.99121 529.62585 lineto
+252.63378 529.62586 253.13053 529.45952 253.48145 529.12683 curveto
+253.83235 528.79415 254.00781 528.3202 254.00781 527.70496 curveto
+254.00781 527.09429 253.83235 526.62261 253.48145 526.28992 curveto
+253.13053 525.95724 252.63378 525.7909 251.99121 525.79089 curveto
+250.25488 525.79089 lineto
+248.87402 524.65613 moveto
+251.99121 524.65613 lineto
+253.13509 524.65614 253.99869 524.9159 254.58203 525.43542 curveto
+255.16991 525.95041 255.46386 526.70692 255.46387 527.70496 curveto
+255.46386 528.71212 255.16991 529.47319 254.58203 529.98816 curveto
+253.99869 530.50314 253.13509 530.76062 251.99121 530.76062 curveto
+250.25488 530.76062 lineto
+250.25488 534.86218 lineto
+248.87402 534.86218 lineto
+248.87402 524.65613 lineto
+fill
+grestore
+gsave
+0 0 0 setrgbcolor
+newpath
+257.68555 533.70007 moveto
+259.94141 533.70007 lineto
+259.94141 525.91394 lineto
+257.4873 526.40613 lineto
+257.4873 525.14832 lineto
+259.92773 524.65613 lineto
+261.30859 524.65613 lineto
+261.30859 533.70007 lineto
+263.56445 533.70007 lineto
+263.56445 534.86218 lineto
+257.68555 534.86218 lineto
+257.68555 533.70007 lineto
+fill
+grestore
+0 0 0 setrgbcolor
+[] 0 setdash
+1 setlinewidth
+0 setlinejoin
+0 setlinecap
+newpath
+155 302.36218 moveto
+154.5 534.36218 lineto
+stroke
+grestore
+showpage
+%%EOF
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id: indexset.cc 1728 2012-11-06 13:06:44Z christi $
+
+#include "config.h"
+
+#include <dune/common/parallel/indexset.hh>
+#include <dune/common/parallel/plocalindex.hh>
+#include <dune/common/parallel/mpihelper.hh>
+#include <iostream>
+#include "buildindexset.hh"
+#include "reverse.hh"
+
+int main(int argc, char **argv)
+{
+ // This is a parallel programm so we need to
+ // initialize mpi first.
+ Dune::MPIHelper& helper = Dune::MPIHelper::instance(argc, argv);
+
+ // The rank of our process
+ int rank = helper.rank();
+
+ // The type used as the local index
+ typedef Dune::ParallelLocalIndex<Flag> LocalIndex;
+
+ // The type used as the global index
+ typedef int GlobalIndex;
+
+ // The index set we use to identify the local indices with the globally
+ // unique ones
+ typedef Dune::ParallelIndexSet<GlobalIndex,LocalIndex,100> ParallelIndexSet;
+
+ // The index set
+ ParallelIndexSet indexSet;
+
+ build(helper, indexSet);
+
+ // Print the index set
+ std::cout<<indexSet<<std::endl;
+
+
+ reverseLocalIndex(indexSet);
+
+ // Print the index set
+ if(rank==0)
+ std::cout<<"Reordered lcoal indices:"<<std::endl;
+
+ // Wait for all processes
+ helper.getCollectiveCommunication().barrier();
+
+ std::cout<<indexSet<<std::endl;
+ // Assign new local indices
+
+ return 0;
+}
--- /dev/null
+// -*- 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/exceptions.hh> // We use exceptions
+#include <dune/common/parallel/mpihelper.hh> // An initializer of MPI
+#include <dune/common/parallel/indexset.hh>
+#include <dune/common/parallel/plocalindex.hh>
+
+enum Flags { owner, ghost };
+
+struct Bla
+{
+
+ /** @brief The local index. */
+ size_t localIndex_;
+
+ /** @brief An attribute for the index. */
+ char attribute_;
+
+ /** @brief True if the index is also known to other processors. */
+ bool public_;
+
+ /**
+ * @brief The state of the index.
+ *
+ * Has to be one of LocalIndexState!
+ * @see LocalIndexState.
+ */
+ char state_;
+};
+
+
+template<typename T1, typename T2>
+void buildBlockedIndexSet(T1& indexset, int N, const T2& comm)
+{
+ int rank=comm.rank();
+ int size=comm.size();
+ int localsize=N/size;
+ int bigger=N%size;
+ int start, end;
+ if(rank<bigger) {
+ start=rank*(localsize+1);
+ end=start+(localsize+1);
+ }else{
+ start=bigger*(localsize+1)+(rank-bigger)*localsize;
+ end=start+localsize;
+ }
+
+ indexset.beginResize();
+ int index=0;
+ int gindex=start;
+ typedef typename T1::LocalIndex LocalIndex;
+
+ std::cout<<sizeof(LocalIndex)<<" "<<sizeof(Bla)<<std::endl;
+
+ if(start>0)
+ indexset.add(gindex-1,LocalIndex(index++,ghost));
+
+ for(int i=start; i<end; i++,index++,gindex++)
+ indexset.add(gindex,LocalIndex(index,owner,true));
+
+ if(end<N)
+ indexset.add(gindex,LocalIndex(index,ghost,true));
+}
+int main(int argc, char** argv)
+{
+ int n=100;
+ try{
+ using namespace Dune;
+
+ //Maybe initialize Mpi
+ MPIHelper& helper = MPIHelper::instance(argc, argv);
+ std::cout << "Hello World! This is poosc08." << std::endl;
+ if(Dune::MPIHelper::isFake)
+ std::cout<< "This is a sequential program." << std::endl;
+ else{
+ typedef ParallelIndexSet<int,ParallelLocalIndex<Flags> > IndexSet;
+ IndexSet blockedSet;
+ buildBlockedIndexSet(blockedSet, n, helper.getCollectiveCommunication());
+ }
+ return 0;
+ }
+ catch (Dune::Exception &e) {
+ std::cerr << "Dune reported error: " << e << std::endl;
+ }
+ catch (...) {
+ std::cerr << "Unknown exception thrown!" << std::endl;
+ }
+}
--- /dev/null
+// -*- 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/exceptions.hh> // We use exceptions
+#include <dune/common/parallel/mpihelper.hh> // An initializer of MPI
+#include <dune/common/parallel/indexset.hh>
+#include <dune/common/parallel/remoteindices.hh>
+#include <dune/common/parallel/communicator.hh>
+#include <dune/common/parallel/plocalindex.hh>
+#include <dune/common/parallel/interface.hh>
+#include <dune/common/enumset.hh>
+
+enum Flags { owner, ghost };
+
+template<typename T>
+struct AddData {
+ typedef typename T::value_type IndexedType;
+
+ static const IndexedType& gather(const T& v, int i){
+ return v[i];
+ }
+
+ static void scatter(T& v, const IndexedType& item, int i){
+ v[i]+=item;
+ }
+};
+
+template<typename T>
+struct CopyData {
+ typedef typename T::value_type IndexedType;
+
+ static const IndexedType& gather(const T& v, int i){
+ return v[i];
+ }
+
+ static void scatter(T& v, const IndexedType& item, int i){
+ v[i]=item;
+ }
+};
+
+
+template<class T>
+void doCalculations(T&){}
+
+#if HAVE_MPI
+void test()
+{
+ int rank;
+ MPI_Comm comm=(MPI_COMM_WORLD);
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+ using namespace Dune;
+ // shortcut for index set type
+ typedef ParallelLocalIndex<Flags> LocalIndex;
+ typedef ParallelIndexSet<int, LocalIndex > PIndexSet;
+ PIndexSet sis;
+ sis.beginResize();
+ if(rank==0) {
+
+ sis.add(11, LocalIndex(0, ghost));
+ for(int i=1; i<=6; i++)
+ sis.add(i-1, LocalIndex(i, owner, i<=1||i>5));
+ sis.add(6, LocalIndex(7, ghost));
+ }else{
+ sis.add(5, LocalIndex(0, ghost));
+ for(int i=1; i<=6; i++)
+ sis.add(5+i, LocalIndex(i, owner, i<=1||i>5));
+ sis.add(0,LocalIndex(7, ghost));
+ }
+ sis.endResize();
+
+ PIndexSet tis;
+ tis.beginResize();
+ int l=0;
+ for(int i=0; i<2; ++i)
+ for(int j=0; j<5; ++j) {
+ int g=rank*3-1+i*6+j;
+ if(g<0||g>11)
+ continue;
+ Flags flag=(j>0&&j<4) ? owner : ghost;
+ tis.add(g, LocalIndex(l++, flag));
+ }
+ tis.endResize();
+ std::cout<<rank<<" isxset: "<<sis<<std::endl;
+
+ RemoteIndices<PIndexSet> riRedist(sis, tis, comm);
+ riRedist.rebuild<true>();
+
+ std::vector<int> v;
+ RemoteIndices<PIndexSet> riS(sis,sis, comm, v, true);
+ riS.rebuild<false>();
+
+ std::cout<<std::endl<<"begin"<<rank<<" riS="<<riS<<" end"<<rank<<std::endl<<std::endl;
+
+ Combine<EnumItem<Flags,ghost>,EnumItem<Flags,owner>,Flags> ghostFlags;
+ EnumItem<Flags,owner> ownerFlags;
+ Combine<EnumItem<Flags,ghost>, EnumItem<Flags,owner> > allFlags;
+
+ Interface infRedist;
+ Interface infS;
+
+ infRedist.build(riRedist, ownerFlags, allFlags);
+ infS.build(riS, ownerFlags, ghostFlags);
+
+ std::cout<<"inf "<<rank<<": "<<infS<<std::endl;
+
+ typedef std::vector<double> Container;
+ Container s(sis.size(),3), t(tis.size());
+
+ s[sis.size()-1]=-1;
+
+ BufferedCommunicator bComm;
+ BufferedCommunicator bCommRedist;
+ bComm.build(s, s, infS);
+ //bCommRedist.build(s, t, infRedist);
+ for(std::size_t i=0; i<sis.size(); i++)
+ std::cout<<s[i]<<" ";
+ std::cout<<std::endl;
+
+ bComm.forward<CopyData<Container> >(s,s);
+
+ for(std::size_t i=0; i<sis.size(); i++)
+ std::cout<<s[i]<<" ";
+ std::cout<<std::endl;
+ //bCommRedist.forward<CopyData<Container> >(s,t);
+ // calculate on the redistributed array
+ doCalculations(t);
+ bCommRedist.backward<AddData<Container> >(s,t);
+}
+#endif // HAVE_MPI
+
+int main(int argc, char** argv)
+{
+ try{
+ using namespace Dune;
+#if HAVE_MPI
+ //Maybe initialize Mpi
+ MPIHelper& helper = MPIHelper::instance(argc, argv);
+ std::cout << "Hello World! This is poosc08. rank=" <<helper.rank()<< std::endl;
+ test();
+ return 0;
+#else
+ std::cout<< "Test poosc08_test disabled because MPI is not available." << std::endl;
+ return 77;
+#endif // HAVE_MPI
+ }
+ catch (Dune::Exception &e) {
+ std::cerr << "Dune reported error: " << e << std::endl;
+ }
+ catch (...) {
+ std::cerr << "Unknown exception thrown!" << std::endl;
+ }
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id: reverse.hh 942 2008-09-10 18:21:57Z christi $
+#ifndef REVERSE_HH
+#define REVERSE_HH
+
+#include "buildindexset.hh"
+
+/**
+ * @brief Reverse the local indices of an index set.
+ *
+ * Let the index set have N entries than the index 0 will become N-1,
+ * 1 become N-2, ..., and N-1 will become 0.
+ * @param indexSet The index set to reverse.
+ */
+template<typename TG, typename TL, int N>
+void reverseLocalIndex(Dune::ParallelIndexSet<TG,TL,N>& indexSet)
+{
+ // reverse the local indices
+ typedef typename Dune::ParallelIndexSet<TG,TL,N>::iterator iterator;
+
+ iterator end = indexSet.end();
+ size_t maxLocal = 0;
+
+ // find the maximal local index
+ for(iterator index = indexSet.begin(); index != end; ++index) {
+ // Get the local index
+ LocalIndex& local = index->local();
+ maxLocal = std::max(maxLocal, local.local());
+ }
+
+ for(iterator index = indexSet.begin(); index != end; ++index) {
+ // Get the local index
+ LocalIndex& local = index->local();
+ local = maxLocal--;
+ }
+
+}
+#endif
--- /dev/null
+.deps
+Doxyfile
+Doxyfile.in
+doxy-header.html
+doxy-footer.html
+bestpractice.html
+doxygen-tag
+doxygen.log
+doxyerr.log
+html
+html-dist
+latex
+Makefile
+Makefile.in
+semantic.cache
--- /dev/null
+# quickhack for creating the Doxyfile.in and Doxyfile
+add_doxygen_target()
+install(FILES Doxystyle DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/dune-common/doc/doxygen)
--- /dev/null
+# Where to search and which files to use
+INPUT += @srcdir@/mainpage \
+ @srcdir@/modules \
+ @top_srcdir@/dune/common/modules \
+ @top_srcdir@/dune/common
+EXCLUDE += @top_srcdir@/dune/common/test \
+ @top_srcdir@/dune/common/debugallocator.cc
+
--- /dev/null
+#----------- Doxystyle -----------
+
+##################################################################################
+# Project Details:
+
+PROJECT_NAME = @DUNE_MOD_NAME@
+PROJECT_NUMBER = @DUNE_MOD_VERSION@
+
+##################################################################################
+# What to parse
+
+RECURSIVE = YES
+FILE_PATTERNS = *.hh \
+ *.cc
+INPUT =
+EXCLUDE =
+
+EXCLUDE_PATTERNS = */.svn/* */test/*
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = NO # don't warn about missing stl-headers etc.
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH = @abs_top_srcdir@
+
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = NO
+WARN_LOGFILE = doxyerr.log
+
+#################################################################################
+# Styling
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+@DUNEWEB_TRUE@SHORT_NAMES = NO
+@DUNEWEB_FALSE@SHORT_NAMES = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = YES
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION = YES
+ALPHABETICAL_INDEX = YES
+COLS_IN_ALPHA_INDEX = 3
+HTML_OUTPUT = html
+SEARCHENGINE = NO
+
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+
+GENERATE_HTML = YES
+GENERATE_DOCSET = NO
+GENERATE_HTMLHELP = NO
+GENERATE_CHI = NO
+GENERATE_QHP = NO
+GENERATE_TREEVIEW = NO
+
+GENERATE_LATEX = NO
+GENERATE_RTF = NO
+GENERATE_MAN = NO
+GENERATE_XML = NO
+GENERATE_AUTOGEN_DEF = NO
+GENERATE_PERLMOD = NO
+GENERATE_TAGFILE =
+GENERATE_LEGEND = NO
+
+MACRO_EXPANSION = YES
+EXPAND_ONLY_PREDEF = YES
+PREDEFINED = DOXYGEN \
+ HAVE_MPI:=1 \
+ _DEBUG_ALLOCATOR_H:=1 \
+ "DUNE_DEPRECATED:=/** \deprecated */" \
+ "DUNE_DEPRECATED_MSG(A):=/** \deprecated A */"
+
+@DOT_TRUE@HAVE_DOT = YES
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = YES
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = NO
+GROUP_GRAPHS = YES
+INCLUDE_GRAPH = NO
+INCLUDED_BY_GRAPH = NO
+GRAPHICAL_HIERARCHY = NO
+DOT_MULTI_TARGETS = NO
+GENERATE_LEGEND = NO
+DOT_CLEANUP = NO
+
+####################################################################
+# Header Footer and Stylesheet in use is controled by the Makefile #
+# (christi 16. Jan 2006) #
+####################################################################
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+@DUNEWEB_TRUE@HTML_HEADER = doxy-header.html
+@DUNEWEB_FALSE@HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+@DUNEWEB_TRUE@HTML_FOOTER = doxy-footer.html
+@DUNEWEB_FALSE@HTML_FOOTER =
+
+########################## DOXYGEN DOXYSTYLE
+EXTRACT_ALL = YES
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = YES
+EXTRACT_LOCAL_CLASSES = YES
+EXTRACT_LOCAL_METHODS = NO
+EXTRACT_ANON_NSPACES = NO
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = NO
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = NO
+SORT_MEMBERS_CTORS_1ST = NO
+SORT_GROUP_NAMES = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_FILES = YES
+SHOW_NAMESPACES = YES
+FILE_VERSION_FILTER =
+LAYOUT_FILE =
--- /dev/null
+# $Id$
+
+doxydir = $(pkgdatadir)/doc/doxygen
+
+dist_doxy_DATA = \
+ Doxystyle
+
+# setting like in dune-web
+BASEDIR=../..
+CURDIR=doc/doxygen
+PAGES =
+
+# add some more stuff to install and tarball
+DOCFILES = $(PAGES)
+EXTRA_DIST = CMakeLists.txt $(PAGES) Doxylocal
+
+include $(top_srcdir)/am/doxygen
+include $(top_srcdir)/am/global-rules
--- /dev/null
+/** \mainpage dune-common Automatic Documentation
+
+\section intro Introduction
+
+Welcome to the %Dune documentation pages. This documentation has been
+generated using Doxygen, a free source code documentation system for
+documenting C/C++ code.
+
+\section mods Modules
+
+The best way to start is from the page \subpage modules which gives
+you access to the documentation by category.
+
+*/
+
+/** \page modules Modules
+*/
--- /dev/null
+/**
+ @defgroup Common Common (foundation classes)
+*/
+
+/**
+ @defgroup Allocators Allocators
+ @brief Implementations of the STL allocator concept
+ @ingroup Common
+*/
--- /dev/null
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH DUNECONTROL 1 "November 26, 2013"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh disable hyphenation
+.\" .hy enable hyphenation
+.\" .ad l left justify
+.\" .ad b justify to both left and right margins
+.\" .nf disable filling
+.\" .fi enable filling
+.\" .br insert line break
+.\" .sp <n> insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+dunecontrol \- Control program for the Dune build system
+.SH SYNOPSIS
+.B dunecontrol
+[\fIOPTIONS\fP] \fICOMMANDS\fP [\fICOMMAND-OPTIONS\fP]
+.SH DESCRIPTION
+.B dunecontrol
+is the control program for the build system of the Dune libraries.
+
+The Dune libraries form a set of modules. Each can be built independently using either
+the AutoTools or cmake. Additionally, though, there are dependencies between modules,
+which are expected to form a directed acyclic graph. These dependencies are set in a
+file called
+.B dune.module
+contained in the main directory of a Dune module.
+
+The
+.B dunecontrol
+program helps to build sets of inter-dependent modules. It allows to construct
+the entire dependency graph and obtain information about it. Then it allows to give various build-related
+commands for all modules. These are executed in the order mandated by the dependency graph.
+
+.SH COMMANDS
+Colon-separated list of commands. Available commands are:
+.HP
+.B help
+.IP
+Shows a help message and exits
+.HP
+.B print
+.IP
+Print the list of modules sorted after their dependencies
+.HP
+.B info
+.IP
+Same as `print', but including whether it is a dependency or suggestion
+.HP
+.B printdeps
+.IP
+Print recursive dependencies of a module
+.HP
+.B vcsetup
+.IP
+Setup version control repository (Git etc.) or working copy (SVN)
+.HP
+.B update
+.IP
+Update all modules from the repository
+.HP
+.B autogen
+.IP
+Run the autogen.sh script for each module. Does nothing, if CMake is activated
+.HP
+.B configure
+.IP
+Run configure or cmake for each module
+.HP
+.B make
+.IP
+Run make for each module
+.HP
+.B all
+.IP
+Run the 'autogen', 'configure' and 'make' commands for each module
+.HP
+.B exec
+.IP
+Execute an arbitrary command in each module source directory
+.HP
+.B bexec
+.IP
+Execute an arbitrary command in each module build directory
+.HP
+.B status
+.IP
+Show version control status for all modules
+.HP
+.B svn
+.IP
+Run svn command for each svn managed module
+.HP
+.B git
+.IP
+Run git command for each git managed module
+.HP
+.B export
+.IP
+Run eval `dunecontrol export` to save the list of dune.module files to the DUNE_CONTROL_PATH variable
+.SH OPTIONS
+.HP
+\fB\-h\fP, \fB\-\-help\fP
+.IP
+Show this help
+.HP
+\fB--debug\fP
+.IP
+Run with debuggin output enabled
+.HP
+\fB--use-cmake\fP
+.IP
+Use cmake instead of the AutoTools for building individual modules
+.HP
+\fB--module=\fP\fImod\fP
+.IP
+Only apply the actions on module
+.I mod
+and all modules it depends on
+.HP
+\fB--only=\fP\fImod\fP
+.IP
+Only apply the actions on module
+.I mod
+, but not the modules it depends on
+.HP
+\fB--current\fP
+.IP
+Only apply the actions on the current module, the one whose source tree we are in
+.HP
+\fB--resume\fP
+.IP
+Resume a previous run (only consider the modules not built successfully on the previous run)
+.HP
+\fB--skipfirst\fP
+.IP
+Skip the first module (use with --resume)
+.HP
+\fB--opts=\fP\fIfile\fP
+.IP
+Load default options from \fIfile\fP (see dune-common/doc/example.opts)
+.HP
+\fB--builddir=\fP\fIname\fP
+.IP
+Make out-of-source builds in a subdir \fIname\fP. This directory is created inside each module.
+.HP
+\fB--[COMMAND]-opts=\fP\fIopts\fP
+.IP
+Set options for COMMAND (this is mainly useful for the 'all' COMMAND)
+
+
+.SH ENVIRONMENT VARIABLES
+.B dunecontrol
+looks for Dune modules in all directories given in the
+.B DUNE_CONTROL_PATH
+variable, and additionally recursively in all subdirectories of those directories.
+The default for the case that DUNE_CONTROL_PATH is empty is the current directory,
+plus a system-wide installation in /usr.
+
+.SH AUTHOR
+Dune was written by the Dune team (www.dune-project.org/people).
+.PP
+This manual page was written by Oliver Sander.
+
+.SH COPYRIGHT
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved. This file is offered as-is,
+without any warranty.
--- /dev/null
+# use these options for configure if no options a provided on the cmdline
+AUTOGEN_FLAGS="--ac=2.50 --am=-1.8"
+CONFIGURE_FLAGS="CXX=g++-3.4 --prefix='/tmp/Hu Hu'"
+MAKE_FLAGS=install
--- /dev/null
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+CXX=@CXX@
+CC=@CC@
+DEPENDENCIES=@REQUIRES@
+
+Name: @PACKAGE_NAME@
+Version: @VERSION@
+Description: Dune (Distributed and Unified Numerics Environment) common module
+URL: http://dune-project.org/
+Requires: ${DEPENDENCIES}
+Libs: -L${libdir} -ldunecommon
+Cflags: -I${includedir}
--- /dev/null
+Module: dune-common
+Version: 2.3.1
+Maintainer: dune-devel@dune-project.org
+Whitespace-Hook: Yes
--- /dev/null
+Makefile.in
+Makefile
--- /dev/null
+add_subdirectory("common")
--- /dev/null
+# $Id: $
+
+SUBDIRS = common
+
+include $(top_srcdir)/am/global-rules
+
+EXTRA_DIST = CMakeLists.txt
--- /dev/null
+add_subdirectory("parallel")
+add_subdirectory("std")
+add_subdirectory("test" EXCLUDE_FROM_ALL)
+
+#build the library dunecommon
+if(LAPACK_FOUND)
+ set(_additional_libs ${LAPACK_LIBRARIES})
+elseif(BLAS_FOUND)
+ set(_additional_libs ${BLAS_LIBRARIES})
+endif(LAPACK_FOUND)
+
+dune_add_library("dunecommon"
+ debugallocator.cc
+ dynmatrixev.cc
+ exceptions.cc
+ fmatrixev.cc
+ ios_state.cc
+ parametertree.cc
+ parametertreeparser.cc
+ path.cc
+ stdstreams.cc
+ ADD_LIBS "${_additional_libs}")
+
+#install headers
+install(FILES
+ alignment.hh
+ array.hh
+ arraylist.hh
+ bartonnackmanifcheck.hh
+ bigunsignedint.hh
+ binaryfunctions.hh
+ bitsetvector.hh
+ classname.hh
+ collectivecommunication.hh
+ debugallocator.hh
+ debugstream.hh
+ deprecated.hh
+ densematrix.hh
+ densevector.hh
+ diagonalmatrix.hh
+ documentation.hh
+ dotproduct.hh
+ dynmatrix.hh
+ dynmatrixev.hh
+ dynvector.hh
+ enumset.hh
+ exceptions.hh
+ fassign.hh
+ float_cmp.cc
+ float_cmp.hh
+ fmatrix.hh
+ fmatrixev.hh
+ forloop.hh
+ ftraits.hh
+ function.hh
+ fvector.hh
+ gcd.hh
+ genericiterator.hh
+ gmpfield.hh
+ hash.hh
+ identitymatrix.hh
+ indent.hh
+ interfaces.hh
+ ios_state.hh
+ iteratorfacades.hh
+ lcm.hh
+ lru.hh
+ mallocallocator.hh
+ math.hh
+ matvectraits.hh
+ misc.hh
+ mpicollectivecommunication.hh
+ mpiguard.hh
+ mpihelper.hh
+ mpitraits.hh
+ nullptr.hh
+ parametertree.hh
+ parametertreeparser.hh
+ path.hh
+ poolallocator.hh
+ power.hh
+ precision.hh
+ propertymap.hh
+ promotiontraits.hh
+ reservedvector.hh
+ shared_ptr.hh
+ singleton.hh
+ sllist.hh
+ static_assert.hh
+ stdstreams.hh
+ stringutility.hh
+ timer.hh
+ tuples.hh
+ tupleutility.hh
+ typetraits.hh
+ unused.hh
+ version.hh
+ visibility.hh
+DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/common)
+
+# Install some test headers, because they get used by tests in other modules
+# We do this here as test will not be considered for make install
+install(FILES test/iteratortest.hh
+ test/checkmatrixinterface.hh
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/common/test)
--- /dev/null
+# $Id$
+
+SUBDIRS = . test parallel std
+
+# the standard debug streams are put into the libdune
+noinst_LTLIBRARIES = libcommon.la
+
+libcommon_la_SOURCES = \
+ debugallocator.cc \
+ fmatrixev.cc \
+ dynmatrixev.cc \
+ ios_state.cc \
+ parametertree.cc \
+ parametertreeparser.cc \
+ path.cc \
+ exceptions.cc \
+ stdstreams.cc
+libcommon_la_LIBADD = $(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS) $(FLIBS)
+
+commonincludedir = $(includedir)/dune/common
+commoninclude_HEADERS = \
+ alignment.hh \
+ array.hh \
+ arraylist.hh \
+ bartonnackmanifcheck.hh \
+ bigunsignedint.hh \
+ binaryfunctions.hh \
+ bitsetvector.hh \
+ classname.hh \
+ collectivecommunication.hh \
+ debugallocator.hh \
+ debugstream.hh \
+ deprecated.hh \
+ densematrix.hh \
+ densevector.hh \
+ diagonalmatrix.hh \
+ documentation.hh \
+ dotproduct.hh \
+ dynmatrix.hh \
+ dynvector.hh \
+ dynmatrixev.hh \
+ enumset.hh \
+ exceptions.hh \
+ fassign.hh \
+ float_cmp.cc \
+ float_cmp.hh \
+ fmatrix.hh \
+ fmatrixev.hh \
+ forloop.hh \
+ ftraits.hh \
+ function.hh \
+ fvector.hh \
+ gcd.hh \
+ genericiterator.hh \
+ gmpfield.hh \
+ hash.hh \
+ identitymatrix.hh \
+ indent.hh \
+ interfaces.hh \
+ ios_state.hh \
+ iteratorfacades.hh \
+ lcm.hh \
+ lru.hh \
+ mallocallocator.hh \
+ math.hh \
+ matvectraits.hh \
+ misc.hh \
+ mpicollectivecommunication.hh \
+ mpiguard.hh \
+ mpihelper.hh \
+ mpitraits.hh \
+ nullptr.hh \
+ parametertree.hh \
+ parametertreeparser.hh \
+ path.hh \
+ poolallocator.hh \
+ power.hh \
+ precision.hh \
+ promotiontraits.hh \
+ propertymap.hh \
+ reservedvector.hh \
+ shared_ptr.hh \
+ singleton.hh \
+ sllist.hh \
+ static_assert.hh \
+ stdstreams.hh \
+ stringutility.hh \
+ timer.hh \
+ tuples.hh \
+ tupleutility.hh \
+ typetraits.hh \
+ unused.hh \
+ version.hh \
+ visibility.hh
+
+include $(top_srcdir)/am/global-rules
+
+EXTRA_DIST = CMakeLists.txt
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+#ifndef DUNE_ALIGNMENT_HH
+#define DUNE_ALIGNMENT_HH
+#include <cstddef>
+#if HAVE_TYPE_TRAITS
+#include <type_traits>
+#elif HAVE_TR1_TYPE_TRAITS
+#include <tr1/type_traits>
+#endif
+
+namespace Dune
+{
+
+ /** @addtogroup Common
+ *
+ * @{
+ */
+ /**
+ * @file
+ * @brief This file implements a template class to determine alignment
+ * requirements of types at compile time.
+ * @author Markus Blatt
+ */
+
+ namespace
+ {
+
+ /**
+ * @brief Helper class to measure alignment requirement.
+ * @tparam T The type we want to measure the alignment requirement for.
+ */
+ template<class T>
+ struct AlignmentStruct
+ {
+ char c;
+ T t;
+ void hack();
+ };
+
+ /**
+ * @brief Helper class to measure alignment requirement.
+ * @tparam T The type we want to measure the alignment requirement for.
+ */
+ template<class T, std::size_t N>
+ struct AlignmentHelper
+ {
+ enum { N2 = sizeof(AlignmentStruct<T>) - sizeof(T) - N };
+ char padding1[N];
+ T t;
+ char padding2[N2];
+ };
+
+#define ALIGNMENT_MODULO(a, b) (a % b == 0 ? \
+ static_cast<std::size_t>(b) : \
+ static_cast<std::size_t>(a % b))
+#define ALIGNMENT_MIN(a, b) (static_cast<std::size_t>(a) < \
+ static_cast<std::size_t>(b) ? \
+ static_cast<std::size_t>(a) : \
+ static_cast<std::size_t>(b))
+ /** @brief does the actual calculations. */
+ template <class T, std::size_t N>
+ struct AlignmentTester
+ {
+ typedef AlignmentStruct<T> s;
+ typedef AlignmentHelper<T, N> h;
+ typedef AlignmentTester<T, N - 1> next;
+ enum
+ {
+ a1 = ALIGNMENT_MODULO(N , sizeof(T)),
+ a2 = ALIGNMENT_MODULO(h::N2 , sizeof(T)),
+ a3 = ALIGNMENT_MODULO(sizeof(h), sizeof(T)),
+ a = sizeof(h) == sizeof(s) ? ALIGNMENT_MIN(a1, a2) : a3,
+ result = ALIGNMENT_MIN(a, next::result)
+ };
+ };
+
+ /** @brief does the actual calculations. */
+ template <class T>
+ struct AlignmentTester<T, 0>
+ {
+ enum
+ {
+ result = ALIGNMENT_MODULO(sizeof(AlignmentStruct<T>), sizeof(T))
+ };
+ };
+ } //end anonymous namespace
+
+ /**
+ * @brief Calculates the alignment requirement of a type.
+ *
+ * @see http://en.wikipedia.org/wiki/Data_structure_alignment
+ *
+ * This will be a safe value and not an optimal one.
+ * If TR1 is available it falls back to std::alignment_of.
+ */
+ template <class T>
+ struct AlignmentOf
+ {
+
+ enum
+ {
+ /** @brief The alignment requirement. */
+#ifdef HAVE_TYPE_TRAITS
+ value = std::alignment_of<T>::value
+#elif HAVE_TR1_TYPETRAITS
+ value = std::tr1::alignment_of<T>::value
+#else
+ value = AlignmentTester<T, sizeof(AlignmentStruct<T>) - sizeof(T) -1>::result
+#endif
+ };
+ };
+
+ /** @} */
+}
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+
+#ifndef DUNE_ARRAY_HH
+#define DUNE_ARRAY_HH
+
+/** \file
+ \brief Fallback implementation of the std::array class (a static array)
+ */
+
+#include <iostream>
+#include <iomanip>
+#include <string>
+
+// Include system implementation of array class if present
+#ifdef HAVE_ARRAY
+#include <array>
+#else
+#include <algorithm>
+#endif
+
+#include "deprecated.hh"
+
+namespace Dune
+{
+ /** @addtogroup Common
+
+ @{
+ */
+
+#ifdef HAVE_ARRAY
+ using std::array;
+#else
+
+ /** \brief Simple fixed size array class. This replaces std::array,
+ * if that is not available.
+ *
+ */
+ template<class T, size_t N>
+ class array {
+ public:
+
+ //! Remember the storage type
+ typedef T value_type;
+
+ /** \brief Reference to an object */
+ typedef value_type& reference;
+
+ /** \brief Const reference to an object */
+ typedef const value_type& const_reference;
+
+ /** \brief Iterator type */
+ typedef value_type* iterator;
+
+ /** \brief Const iterator type */
+ typedef const value_type* const_iterator;
+
+ /** \brief Type used for array indices */
+ typedef std::size_t size_type;
+
+ /** \brief Difference type */
+ typedef std::ptrdiff_t difference_type;
+
+ /** \brief Reverse iterator type */
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+
+ /** \brief Const reverse iterator type */
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ /** \brief Return array size */
+ size_type size() const {return N;}
+
+ //! Assign value to all entries
+ array<T,N>& operator= (const T& t)
+ {
+ fill(t);
+ return (*this);
+ }
+
+ //! \brief Assign value to all entries (according to C++0x the fill method is to be prefered)
+ void assign(const T& t) DUNE_DEPRECATED
+ {
+ fill(t);
+ }
+
+ //! \brief Assign value to all entries (according to C++0x the fill method is to be prefered)
+ void fill(const T& t)
+ {
+ for (size_type i=0; i<N; i++) a[i]=t;
+ }
+
+ //! Component access
+ reference operator[] (size_type i)
+ {
+ return a[i];
+ }
+
+ //! Const component access
+ const_reference operator[] (size_type i) const
+ {
+ return a[i];
+ }
+
+ iterator begin ()
+ {
+ return a;
+ }
+
+ const_iterator begin () const
+ {
+ return a;
+ }
+
+ iterator end ()
+ {
+ return a + N;
+ }
+
+ const_iterator end () const
+ {
+ return a + N;
+ }
+
+ T a[(N > 0) ? N : 1];
+ };
+
+
+
+ // Comparison Operators (see [lib.container.requirements])
+ // -------------------------------------------------------
+
+ template< class T, size_t N >
+ inline bool operator< ( const array< T, N > &a, const array< T, N > &b )
+ {
+ return std::lexicographical_compare( a.begin(), a.end(), b.begin(), b.end() );
+ }
+
+ template< class T, size_t N >
+ inline bool operator> ( const array< T, N > &a, const array< T, N > &b )
+ {
+ return b < a;
+ }
+
+ template< class T, size_t N >
+ inline bool operator<= ( const array< T, N > &a, const array< T, N > &b )
+ {
+ return !(a > b);
+ }
+
+ template< class T, size_t N >
+ inline bool operator>= ( const array< T, N > &a, const array< T, N > &b )
+ {
+ return !(a < b);
+ }
+#endif
+
+ //! Output operator for array
+ template < class T, size_t N >
+ inline std::ostream& operator<< (std::ostream& s, const array<T,N>& e)
+ {
+ if (N == 0)
+ {
+ s << "[]";
+ return s;
+ }
+
+ s << "[";
+ for (size_t i=0; i<N-1; i++) s << e[i] << ",";
+ s << e[N-1] << "]";
+ return s;
+ }
+
+#ifndef DOXYGEN
+ template<class T>
+ array<T, 1> make_array(const T &t0) {
+ array<T, 1> result = { {t0} };
+ return result;
+ }
+
+ template<class T>
+ array<T, 2> make_array(const T &t0, const T &t1) {
+ array<T, 2> result = { {t0, t1} };
+ return result;
+ }
+
+ template<class T>
+ array<T, 3> make_array(const T &t0, const T &t1, const T &t2) {
+ array<T, 3> result = { {t0, t1, t2} };
+ return result;
+ }
+
+ template<class T>
+ array<T, 4> make_array(const T &t0, const T &t1, const T &t2, const T &t3) {
+ array<T, 4> result = { {t0, t1, t2, t3} };
+ return result;
+ }
+
+ template<class T>
+ array<T, 5> make_array(const T &t0, const T &t1, const T &t2, const T &t3,
+ const T &t4)
+ {
+ array<T, 5> result = { {t0, t1, t2, t3, t4} };
+ return result;
+ }
+
+ template<class T>
+ array<T, 6> make_array(const T &t0, const T &t1, const T &t2, const T &t3,
+ const T &t4, const T &t5)
+ {
+ array<T, 6> result = { {t0, t1, t2, t3, t4, t5} };
+ return result;
+ }
+
+ template<class T>
+ array<T, 7> make_array(const T &t0, const T &t1, const T &t2, const T &t3,
+ const T &t4, const T &t5, const T &t6)
+ {
+ array<T, 7> result = { {t0, t1, t2, t3, t4, t5, t6} };
+ return result;
+ }
+
+ template<class T>
+ array<T, 8> make_array(const T &t0, const T &t1, const T &t2, const T &t3,
+ const T &t4, const T &t5, const T &t6, const T &t7)
+ {
+ array<T, 8> result = { {t0, t1, t2, t3, t4, t5, t6, t7} };
+ return result;
+ }
+
+ template<class T>
+ array<T, 9> make_array(const T &t0, const T &t1, const T &t2, const T &t3,
+ const T &t4, const T &t5, const T &t6, const T &t7,
+ const T &t8)
+ {
+ array<T, 9> result = { {t0, t1, t2, t3, t4, t5, t6, t7, t8} };
+ return result;
+ }
+#endif // !DOXYGEN
+
+ //! create an initialize an array
+ /**
+ * \note There are overloads for this method which take fewer arguments
+ * (minimum 1). The current maximum of 10 arguments is arbitrary and
+ * can be raised on demand.
+ * \note This method is Dune-specific and not part of any C++-standard.
+ */
+ template<class T>
+ array<T, 10> make_array(const T &t0, const T &t1, const T &t2, const T &t3,
+ const T &t4, const T &t5, const T &t6, const T &t7,
+ const T &t8, const T &t9)
+ {
+ array<T, 10> result = { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9 };
+ return result;
+ }
+
+ //! Create an array and fill it with copies of the provided value.
+ /**
+ * \note This method is Dune-specific and not part of any C++ standard.
+ */
+ template<typename T, std::size_t n>
+ array<T,n> fill_array(const T& t)
+ {
+ array<T,n> r;
+ r.fill(t);
+#if HAVE_RVALUE_REFERENCES
+ return std::move(r);
+#else
+ return r;
+#endif
+ }
+
+ /** @} */
+
+} // end namespace Dune
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+
+#ifndef DUNE_ARRAYLIST_HH
+#define DUNE_ARRAYLIST_HH
+
+#include <cassert>
+#include <vector>
+#include "shared_ptr.hh"
+#include "array.hh"
+#include "iteratorfacades.hh"
+
+namespace Dune
+{
+ // forward declaration
+ template<class T, int N, class A>
+ class ArrayListIterator;
+
+ template<class T, int N, class A>
+ class ConstArrayListIterator;
+
+ /**
+ * @file
+ * \brief Implements a random-access container that can efficiently change size (similar to std::deque)
+ *
+ * This file implements the class ArrayList which behaves like
+ * dynamically growing array together with
+ * the class ArrayListIterator which is random access iterator as needed
+ * by the stl for sorting and other algorithms.
+ * @author Markus Blatt
+ */
+ /**
+ * @addtogroup Common
+ *
+ * @{
+ */
+
+ /**
+ * @brief A dynamically growing random access list.
+ *
+ * Internally the data is organised in a list of arrays of fixed size.
+ * Whenever the capacity of the array list is not sufficient a new
+ * Dune::array is allocated. In contrast to
+ * std::vector this approach prevents data copying. On the outside
+ * we provide the same interface as the stl random access containers.
+ *
+ * While the concept sounds quite similar to std::deque there are slight
+ * but crucial differences:
+ * - In contrast to std:deque the actual implementation (a list of arrays)
+ * is known. While
+ * for std::deque there are at least two possible implementations
+ * (dynamic array or using a double linked list.
+ * - In contrast to std:deque there is not insert which invalidates iterators
+ * but our push_back method leaves all iterators valid.
+ * - Additional functionality lets one delete entries before and at an
+ * iterator while moving the iterator to the next valid position.
+ */
+ template<class T, int N=100, class A=std::allocator<T> >
+ class ArrayList
+ {
+ public:
+ /**
+ * @brief The member type that is stored.
+ *
+ * Has to be assignable and has to have an empty constructor.
+ */
+ typedef T MemberType;
+
+ /**
+ * @brief Value type for stl compliance.
+ */
+ typedef T value_type;
+
+ /**
+ * @brief The type of a reference to the type we store.
+ */
+ typedef T& reference;
+
+ /**
+ * @brief The type of a const reference to the type we store.
+ */
+ typedef const T& const_reference;
+
+ /**
+ * @brief The type of a pointer to the type we store.
+ */
+ typedef T* pointer;
+
+ /**
+ * @brief The type of a const pointer to the type we store.
+ */
+ typedef const T* const_pointer;
+
+ enum
+ {
+ /**
+ * @brief The number of elements in one chunk of the list.
+ * This has to be at least one. The default is 100.
+ */
+ chunkSize_ = (N > 0) ? N : 1
+ };
+
+ /**
+ * @brief A random access iterator.
+ */
+ typedef ArrayListIterator<MemberType,N,A> iterator;
+
+ /**
+ * @brief A constant random access iterator.
+ */
+ typedef ConstArrayListIterator<MemberType,N,A> const_iterator;
+
+ /**
+ * @brief The size type.
+ */
+ typedef std::size_t size_type;
+
+ /**
+ * @brief The difference type.
+ */
+ typedef std::ptrdiff_t difference_type;
+
+ /**
+ * @brief Get an iterator that is positioned at the first element.
+ * @return The iterator.
+ */
+ iterator begin();
+
+ /**
+ * @brief Get a random access iterator that is positioned at the
+ * first element.
+ * @return The iterator.
+ */
+ const_iterator begin() const;
+
+ /**
+ * @brief Get a random access iterator positioned after the last
+ * element
+ */
+ iterator end();
+
+ /**
+ * @brief Get a random access iterator positioned after the last
+ * element
+ */
+ const_iterator end() const;
+
+ /**
+ * @brief Append an entry to the list.
+ * @param entry The new entry.
+ */
+ inline void push_back(const_reference entry);
+
+ /**
+ * @brief Get the element at specific position.
+ * @param i The index of the position.
+ * @return The element at that position.
+ */
+ inline reference operator[](size_type i);
+
+ /**
+ * @brief Get the element at specific position.
+ * @param i The index of the position.
+ * @return The element at that position.
+ */
+ inline const_reference operator[](size_type i) const;
+
+ /**
+ * @brief Get the number of elements in the list.
+ * @return The number of elements.
+ */
+ inline size_type size() const;
+
+ /**
+ * @brief Purge the list.
+ *
+ * If there are empty chunks at the front all nonempty
+ * chunks will be moved towards the front and the capacity
+ * increases.
+ */
+ inline void purge();
+
+ /**
+ * @brief Delete all entries from the list.
+ */
+ inline void clear();
+ /**
+ * @brief Constructs an Array list with one chunk.
+ */
+ ArrayList();
+
+ private:
+
+ /**
+ * @brief The allocators for the smart pointer.
+ */
+ typedef typename A::template rebind<shared_ptr<array<MemberType,chunkSize_> > >::other
+ SmartPointerAllocator;
+
+ /**
+ * @brief The allocator for the fixed array.
+ */
+ typedef typename A::template rebind<array<MemberType,chunkSize_> >::other
+ ArrayAllocator;
+
+ /**
+ * @brief The iterator needs access to the private variables.
+ */
+ friend class ArrayListIterator<T,N,A>;
+ friend class ConstArrayListIterator<T,N,A>;
+
+ /** @brief the data chunks of our list. */
+ std::vector<shared_ptr<array<MemberType,chunkSize_> >,
+ SmartPointerAllocator> chunks_;
+ /** @brief The current data capacity.
+ * This is the capacity that the list could have theoretically
+ * with this number of chunks. That is chunks * chunkSize.
+ * In practice some of the chunks at the beginning might be empty
+ * (i.e. null pointers in the first start_/chunkSize chunks)
+ * because of previous calls to eraseToHere.
+ * start_+size_<=capacity_ holds.
+ */
+ size_type capacity_;
+ /** @brief The current number of elements in our data structure. */
+ size_type size_;
+ /** @brief The index of the first entry. */
+ size_type start_;
+ /**
+ * @brief Get the element at specific position.
+ *
+ * Index 0 always refers to the first entry in the list
+ * whether it is erased or not!
+ * @param i The index of the position.
+ * @return The element at that position.
+ */
+ inline reference elementAt(size_type i);
+
+ /**
+ * @brief Get the element at specific position.
+ *
+ * Index 0 always refers to the first entry in the list
+ * whether it is erased or not!
+ * @param i The index of the position.
+ * @return The element at that position.
+ */
+ inline const_reference elementAt(size_type i) const;
+ };
+
+
+ /**
+ * @brief A random access iterator for the Dune::ArrayList class.
+ */
+ template<class T, int N, class A>
+ class ArrayListIterator : public RandomAccessIteratorFacade<ArrayListIterator<T,N,A>,
+ typename A::value_type,
+ typename A::reference,
+ typename A::difference_type>
+ {
+
+ friend class ArrayList<T,N,A>;
+ friend class ConstArrayListIterator<T,N,A>;
+ public:
+ /**
+ * @brief The member type.
+ */
+ typedef typename A::value_type MemberType;
+
+ typedef typename A::difference_type difference_type;
+
+ typedef typename A::size_type size_type;
+
+ typedef typename A::reference reference;
+
+ typedef typename A::const_reference const_reference;
+
+ enum
+ {
+ /**
+ * @brief The number of elements in one chunk of the list.
+ *
+ * This has to be at least one. The default is 100.
+ */
+ chunkSize_ = (N > 0) ? N : 1
+ };
+
+
+ /**
+ * @brief Comares two iterators.
+ * @return True if the iterators are for the same list and
+ * at the position.
+ */
+ inline bool equals(const ArrayListIterator<MemberType,N,A>& other) const;
+
+ /**
+ * @brief Comares two iterators.
+ * @return True if the iterators are for the same list and
+ * at the position.
+ */
+ inline bool equals(const ConstArrayListIterator<MemberType,N,A>& other) const;
+
+ /**
+ * @brief Increment the iterator.
+ */
+ inline void increment();
+
+ /**
+ * @brief decrement the iterator.
+ */
+ inline void decrement();
+
+ /**
+ * @brief Get the value of the list at an arbitrary position.
+ * @return The value at that postion.
+ */
+ inline reference elementAt(size_type i) const;
+
+ /**
+ * @brief Access the element at the current position.
+ * @return The element at the current position.
+ */
+ inline reference dereference() const;
+
+ /**
+ * @brief Erase all entries before the current position
+ * and the one at the current position.
+ *
+ * Afterwards the iterator will be positioned at the next
+ * unerased entry or the end if the list is empty.
+ * This does not invalidate any iterators positioned after
+ * the current position but those positioned at previous ones.
+ * @return An iterator to the first position after the deleted
+ * ones or to the end if the list is empty.
+ */
+ inline void eraseToHere();
+
+ /** \todo Please doc me! */
+ inline size_type position(){return position_;}
+
+ /** \todo Please doc me! */
+ inline void advance(difference_type n);
+
+ /** \todo Please doc me! */
+ inline difference_type distanceTo(const ArrayListIterator<T,N,A>& other) const;
+
+ /** \todo Please doc me! */
+ inline ArrayListIterator<T,N,A>& operator=(const ArrayListIterator<T,N,A>& other);
+
+ //! Standard constructor
+ inline ArrayListIterator() : position_(0)
+ {}
+
+ private:
+ /**
+ * @brief Constructor.
+ * @param list The list we are an iterator for.
+ * @param position The initial position of the iterator.
+ */
+ inline ArrayListIterator(ArrayList<T,N,A>& arrayList, size_type position);
+
+ /**
+ * @brief The current postion.
+ */
+ size_type position_;
+ /**
+ * @brief The list we are an iterator for.
+ */
+ ArrayList<T,N,A>* list_;
+ };
+
+ /**
+ * @brief A constant random access iterator for the Dune::ArrayList class.
+ */
+ template<class T, int N, class A>
+ class ConstArrayListIterator
+ : public RandomAccessIteratorFacade<ConstArrayListIterator<T,N,A>,
+ const typename A::value_type,
+ typename A::const_reference,
+ typename A::difference_type>
+ {
+
+ friend class ArrayList<T,N,A>;
+ friend class ArrayListIterator<T,N,A>;
+
+ public:
+ /**
+ * @brief The member type.
+ */
+ typedef typename A::value_type MemberType;
+
+ typedef typename A::difference_type difference_type;
+
+ typedef typename A::size_type size_type;
+
+ typedef typename A::reference reference;
+
+ typedef typename A::const_reference const_reference;
+ enum
+ {
+ /**
+ * @brief The number of elements in one chunk of the list.
+ *
+ * This has to be at least one. The default is 100.
+ */
+ chunkSize_ = (N > 0) ? N : 1
+ };
+
+ /**
+ * @brief Comares to iterators.
+ * @return true if the iterators are for the same list and
+ * at the position.
+ */
+ inline bool equals(const ConstArrayListIterator<MemberType,N,A>& other) const;
+
+ /**
+ * @brief Increment the iterator.
+ */
+ inline void increment();
+
+ /**
+ * @brief decrement the iterator.
+ */
+ inline void decrement();
+
+ /** \todo Please doc me! */
+ inline void advance(difference_type n);
+
+ /** \todo Please doc me! */
+ inline difference_type distanceTo(const ConstArrayListIterator<T,N,A>& other) const;
+
+ /**
+ * @brief Get the value of the list at an arbitrary position.
+ * @return The value at that postion.
+ */
+ inline const_reference elementAt(size_type i) const;
+
+ /**
+ * @brief Access the element at the current position.
+ * @return The element at the current position.
+ */
+ inline const_reference dereference() const;
+
+ inline const ConstArrayListIterator<T,N,A>& operator=(const ConstArrayListIterator<T,N,A>& other);
+
+ inline ConstArrayListIterator() : position_(0)
+ {}
+
+ inline ConstArrayListIterator(const ArrayListIterator<T,N,A>& other);
+
+ private:
+
+ /**
+ * @brief Constructor.
+ * @param list The list we are an iterator for.
+ * @param position The initial position of the iterator.
+ */
+ inline ConstArrayListIterator(const ArrayList<T,N,A>& arrayList, size_type position);
+
+ /**
+ * @brief The current postion.
+ */
+ size_type position_;
+ /**
+ * @brief The list we are an iterator for.
+ */
+ const ArrayList<T,N,A>* list_;
+ };
+
+
+ template<class T, int N, class A>
+ ArrayList<T,N,A>::ArrayList()
+ : capacity_(0), size_(0), start_(0)
+ {
+ chunks_.reserve(100);
+ }
+
+ template<class T, int N, class A>
+ void ArrayList<T,N,A>::clear(){
+ capacity_=0;
+ size_=0;
+ start_=0;
+ chunks_.clear();
+ }
+
+ template<class T, int N, class A>
+ size_t ArrayList<T,N,A>::size() const
+ {
+ return size_;
+ }
+
+ template<class T, int N, class A>
+ void ArrayList<T,N,A>::push_back(const_reference entry)
+ {
+ size_t index=start_+size_;
+ if(index==capacity_)
+ {
+ chunks_.push_back(shared_ptr<array<MemberType,chunkSize_> >(new array<MemberType,chunkSize_>()));
+ capacity_ += chunkSize_;
+ }
+ elementAt(index)=entry;
+ ++size_;
+ }
+
+ template<class T, int N, class A>
+ typename ArrayList<T,N,A>::reference ArrayList<T,N,A>::operator[](size_type i)
+ {
+ return elementAt(start_+i);
+ }
+
+
+ template<class T, int N, class A>
+ typename ArrayList<T,N,A>::const_reference ArrayList<T,N,A>::operator[](size_type i) const
+ {
+ return elementAt(start_+i);
+ }
+
+ template<class T, int N, class A>
+ typename ArrayList<T,N,A>::reference ArrayList<T,N,A>::elementAt(size_type i)
+ {
+ return chunks_[i/chunkSize_]->operator[](i%chunkSize_);
+ }
+
+
+ template<class T, int N, class A>
+ typename ArrayList<T,N,A>::const_reference ArrayList<T,N,A>::elementAt(size_type i) const
+ {
+ return chunks_[i/chunkSize_]->operator[](i%chunkSize_);
+ }
+
+ template<class T, int N, class A>
+ ArrayListIterator<T,N,A> ArrayList<T,N,A>::begin()
+ {
+ return ArrayListIterator<T,N,A>(*this, start_);
+ }
+
+ template<class T, int N, class A>
+ ConstArrayListIterator<T,N,A> ArrayList<T,N,A>::begin() const
+ {
+ return ConstArrayListIterator<T,N,A>(*this, start_);
+ }
+
+ template<class T, int N, class A>
+ ArrayListIterator<T,N,A> ArrayList<T,N,A>::end()
+ {
+ return ArrayListIterator<T,N,A>(*this, start_+size_);
+ }
+
+ template<class T, int N, class A>
+ ConstArrayListIterator<T,N,A> ArrayList<T,N,A>::end() const
+ {
+ return ConstArrayListIterator<T,N,A>(*this, start_+size_);
+ }
+
+ template<class T, int N, class A>
+ void ArrayList<T,N,A>::purge()
+ {
+ // Distance to copy to the left.
+ size_t distance = start_/chunkSize_;
+ if(distance>0) {
+ // Number of chunks with entries in it;
+ size_t chunks = ((start_%chunkSize_ + size_)/chunkSize_ );
+
+ // Copy chunks to the left.
+ std::copy(chunks_.begin()+distance,
+ chunks_.begin()+(distance+chunks), chunks_.begin());
+
+ // Calculate new parameters
+ start_ = start_ % chunkSize_;
+ //capacity += distance * chunkSize_;
+ }
+ }
+
+ template<class T, int N, class A>
+ void ArrayListIterator<T,N,A>::advance(difference_type i)
+ {
+ position_+=i;
+ }
+
+ template<class T, int N, class A>
+ void ConstArrayListIterator<T,N,A>::advance(difference_type i)
+ {
+ position_+=i;
+ }
+
+
+ template<class T, int N, class A>
+ bool ArrayListIterator<T,N,A>::equals(const ArrayListIterator<MemberType,N,A>& other) const
+ {
+ // Makes only sense if we reference a common list
+ assert(list_==(other.list_));
+ return position_==other.position_ ;
+ }
+
+
+ template<class T, int N, class A>
+ bool ArrayListIterator<T,N,A>::equals(const ConstArrayListIterator<MemberType,N,A>& other) const
+ {
+ // Makes only sense if we reference a common list
+ assert(list_==(other.list_));
+ return position_==other.position_ ;
+ }
+
+
+ template<class T, int N, class A>
+ bool ConstArrayListIterator<T,N,A>::equals(const ConstArrayListIterator<MemberType,N,A>& other) const
+ {
+ // Makes only sense if we reference a common list
+ assert(list_==(other.list_));
+ return position_==other.position_ ;
+ }
+
+ template<class T, int N, class A>
+ void ArrayListIterator<T,N,A>::increment()
+ {
+ ++position_;
+ }
+
+ template<class T, int N, class A>
+ void ConstArrayListIterator<T,N,A>::increment()
+ {
+ ++position_;
+ }
+
+ template<class T, int N, class A>
+ void ArrayListIterator<T,N,A>::decrement()
+ {
+ --position_;
+ }
+
+ template<class T, int N, class A>
+ void ConstArrayListIterator<T,N,A>::decrement()
+ {
+ --position_;
+ }
+
+ template<class T, int N, class A>
+ typename ArrayListIterator<T,N,A>::reference ArrayListIterator<T,N,A>::elementAt(size_type i) const
+ {
+ return list_->elementAt(i+position_);
+ }
+
+ template<class T, int N, class A>
+ typename ConstArrayListIterator<T,N,A>::const_reference ConstArrayListIterator<T,N,A>::elementAt(size_type i) const
+ {
+ return list_->elementAt(i+position_);
+ }
+
+ template<class T, int N, class A>
+ typename ArrayListIterator<T,N,A>::reference ArrayListIterator<T,N,A>::dereference() const
+ {
+ return list_->elementAt(position_);
+ }
+
+ template<class T, int N, class A>
+ typename ConstArrayListIterator<T,N,A>::const_reference ConstArrayListIterator<T,N,A>::dereference() const
+ {
+ return list_->elementAt(position_);
+ }
+
+ template<class T, int N, class A>
+ typename ArrayListIterator<T,N,A>::difference_type ArrayListIterator<T,N,A>::distanceTo(const ArrayListIterator<T,N,A>& other) const
+ {
+ // Makes only sense if we reference a common list
+ assert(list_==(other.list_));
+ return other.position_ - position_;
+ }
+
+ template<class T, int N, class A>
+ typename ConstArrayListIterator<T,N,A>::difference_type ConstArrayListIterator<T,N,A>::distanceTo(const ConstArrayListIterator<T,N,A>& other) const
+ {
+ // Makes only sense if we reference a common list
+ assert(list_==(other.list_));
+ return other.position_ - position_;
+ }
+
+ template<class T, int N, class A>
+ ArrayListIterator<T,N,A>& ArrayListIterator<T,N,A>::operator=(const ArrayListIterator<T,N,A>& other)
+ {
+ position_=other.position_;
+ list_=other.list_;
+ return *this;
+ }
+
+ template<class T, int N, class A>
+ const ConstArrayListIterator<T,N,A>& ConstArrayListIterator<T,N,A>::operator=(const ConstArrayListIterator<T,N,A>& other)
+ {
+ position_=other.position_;
+ list_=other.list_;
+ return *this;
+ }
+
+ template<class T, int N, class A>
+ void ArrayListIterator<T,N,A>::eraseToHere()
+ {
+ list_->size_ -= ++position_ - list_->start_;
+ // chunk number of the new position.
+ size_t posChunkStart = position_ / chunkSize_;
+ // number of chunks to deallocate
+ size_t chunks = (position_ - list_->start_ + list_->start_ % chunkSize_)
+ / chunkSize_;
+ list_->start_ = position_;
+
+ // Deallocate memory not needed any more.
+ for(size_t chunk=0; chunk<chunks; chunk++) {
+ --posChunkStart;
+ list_->chunks_[posChunkStart].reset();
+ }
+
+ // Capacity stays the same as the chunks before us
+ // are still there. They null pointers.
+ assert(list_->start_+list_->size_<=list_->capacity_);
+ }
+
+ template<class T, int N, class A>
+ ArrayListIterator<T,N,A>::ArrayListIterator(ArrayList<T,N,A>& arrayList, size_type position)
+ : position_(position), list_(&arrayList)
+ {}
+
+
+ template<class T, int N, class A>
+ ConstArrayListIterator<T,N,A>::ConstArrayListIterator(const ArrayList<T,N,A>& arrayList,
+ size_type position)
+ : position_(position), list_(&arrayList)
+ {}
+
+ template<class T, int N, class A>
+ ConstArrayListIterator<T,N,A>::ConstArrayListIterator(const ArrayListIterator<T,N,A>& other)
+ : position_(other.position_), list_(other.list_)
+ {}
+
+
+ /** @} */
+}
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+/** @file
+ @author Robert Kloefkorn
+ @brief Provides check for implementation of interface methods when using
+ static polymorphism, i.e. the Barton-Nackman trick.
+
+ Use by invoking CHECK_INTERFACE_IMPLEMENTATION(asImp().methodToCheck())
+ and for template methods double (
+ CHECK_INTERFACE_IMPLEMENTATION((asImp().template methodToCheck<param> ())).
+ **/
+
+//- Dune includes
+#include <dune/common/exceptions.hh>
+
+#ifdef CHECK_INTERFACE_IMPLEMENTATION
+#undef CHECK_INTERFACE_IMPLEMENTATION
+#endif
+#ifdef CHECK_AND_CALL_INTERFACE_IMPLEMENTATION
+#undef CHECK_AND_CALL_INTERFACE_IMPLEMENTATION
+#endif
+
+#ifdef NDEBUG
+#define CHECK_INTERFACE_IMPLEMENTATION(dummy)
+#else
+#define CHECK_INTERFACE_IMPLEMENTATION(__interface_method_to_call__) \
+ {\
+ static bool call = false; \
+ if( call == true ) \
+ DUNE_THROW(NotImplemented,"Interface method not implemented!");\
+ call = true; \
+ try { \
+ (__interface_method_to_call__); \
+ call = false; \
+ } \
+ catch ( ... ) \
+ { \
+ call = false; \
+ throw; \
+ } \
+ }
+#endif
+
+/** The macro CHECK_AND_CALL_INTERFACE_IMPLEMENTATION throws an exception,
+ if the interface method ist not implemented and just calls the method
+ otherwise. If NDEBUG is defined no
+ checking is done and the method is just called.
+ */
+#ifdef NDEBUG
+#define CHECK_AND_CALL_INTERFACE_IMPLEMENTATION(__interface_method_to_call__) \
+ (__interface_method_to_call__)
+#else
+#define CHECK_AND_CALL_INTERFACE_IMPLEMENTATION(__interface_method_to_call__) \
+ CHECK_INTERFACE_IMPLEMENTATION(__interface_method_to_call__)
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+
+#ifndef DUNE_BIGUNSIGNEDINT_HH
+#define DUNE_BIGUNSIGNEDINT_HH
+
+#include <iostream>
+#include <limits>
+#include <cstdlib>
+#include <dune/common/exceptions.hh>
+#include <dune/common/hash.hh>
+
+/**
+ * @file
+ * @brief Portable very large unsigned integers
+ * @author Peter Bastian
+ */
+
+namespace Dune
+{
+ /** @addtogroup Common
+ *
+ * @{
+ */
+
+#if HAVE_MPI
+ template<class K>
+ struct MPITraits;
+#endif
+
+ /**
+ * @brief Portable very large unsigned integers
+ *
+ * Implements (arbitrarily) large unsigned integers to be used as global
+ * ids in some grid managers. Size is a template parameter.
+ *
+ * \tparam k Number of bits of the integer type
+ */
+
+ template<int k>
+ class bigunsignedint {
+ public:
+
+ // unsigned short is 16 bits wide, n is the number of digits needed
+ enum { bits=std::numeric_limits<unsigned short>::digits, n=k/bits+(k%bits!=0),
+ hexdigits=4, bitmask=0xFFFF, compbitmask=0xFFFF0000,
+ overflowmask=0x1 };
+
+ //! Construct uninitialized
+ bigunsignedint ();
+
+ //! Construct from signed int
+ bigunsignedint (int x);
+
+ //! Construct from unsigned int
+ bigunsignedint (std::size_t x);
+
+ //! Print number in hex notation
+ void print (std::ostream& s) const ;
+
+ //! add
+ bigunsignedint<k> operator+ (const bigunsignedint<k>& x) const;
+
+ //! subtract
+ bigunsignedint<k> operator- (const bigunsignedint<k>& x) const;
+
+ //! multiply
+ bigunsignedint<k> operator* (const bigunsignedint<k>& x) const;
+
+ //! prefix increment
+ bigunsignedint<k>& operator++ ();
+
+ //! divide
+ //! \warning This function is very slow and its usage should be
+ //! prevented if possible
+ bigunsignedint<k> operator/ (const bigunsignedint<k>& x) const;
+
+ //! modulo
+ //! \warning This function is very slow and its usage should be
+ //! prevented if possible
+ bigunsignedint<k> operator% (const bigunsignedint<k>& x) const;
+
+
+ //! bitwise and
+ bigunsignedint<k> operator& (const bigunsignedint<k>& x) const;
+
+ //! bitwise exor
+ bigunsignedint<k> operator^ (const bigunsignedint<k>& x) const;
+
+ //! bitwise or
+ bigunsignedint<k> operator| (const bigunsignedint<k>& x) const;
+
+ //! bitwise komplement
+ bigunsignedint<k> operator~ () const;
+
+
+ //! left shift1/
+ bigunsignedint<k> operator<< (int i) const;
+
+ //! right shift
+ bigunsignedint<k> operator>> (int i) const;
+
+
+ //! less than
+ bool operator< (const bigunsignedint<k>& x) const;
+
+ //! less than or equal
+ bool operator<= (const bigunsignedint<k>& x) const;
+
+ //! greater than
+ bool operator> (const bigunsignedint<k>& x) const;
+
+ //! greater or equal
+ bool operator>= (const bigunsignedint<k>& x) const;
+
+ //! equal
+ bool operator== (const bigunsignedint<k>& x) const;
+
+ //! not equal
+ bool operator!= (const bigunsignedint<k>& x) const;
+
+
+ //! export to other types
+ // operator unsigned int () const;
+ unsigned int touint() const;
+ /**
+ * @brief Convert to a double.
+ *
+ * @warning Subject to rounding errors!
+ */
+ double todouble() const;
+
+ friend class bigunsignedint<k/2>;
+ friend struct std::numeric_limits< bigunsignedint<k> >;
+
+#if HAVE_DUNE_HASH
+
+ inline friend std::size_t hash_value(const bigunsignedint& arg)
+ {
+ return hash_range(arg.digit,arg.digit + arg.n);
+ }
+
+#endif // HAVE_DUNE_HASH
+
+ private:
+ unsigned short digit[n];
+#if HAVE_MPI
+ friend struct MPITraits<bigunsignedint<k> >;
+#endif
+ inline void assign(std::size_t x);
+
+
+ } ;
+
+ // Constructors
+ template<int k>
+ bigunsignedint<k>::bigunsignedint ()
+ {
+ assign(0u);
+ }
+
+ template<int k>
+ bigunsignedint<k>::bigunsignedint (int y)
+ {
+ std::size_t x = std::abs(y);
+ assign(x);
+ }
+
+ template<int k>
+ bigunsignedint<k>::bigunsignedint (std::size_t x)
+ {
+ assign(x);
+ }
+ template<int k>
+ void bigunsignedint<k>::assign(std::size_t x)
+ {
+ int no=std::min(static_cast<int>(n),
+ static_cast<int>(std::numeric_limits<std::size_t>::digits/bits));
+
+ for(int i=0; i<no; ++i) {
+ digit[i] = (x&bitmask);
+ x=x>>bits;
+ }
+ for (unsigned int i=no; i<n; i++) digit[i]=0;
+ }
+
+ // export
+ template<int k>
+ inline unsigned int bigunsignedint<k>::touint () const
+ {
+ return (digit[1]<<bits)+digit[0];
+ }
+
+ template<int k>
+ inline double bigunsignedint<k>::todouble() const
+ {
+ int firstInZeroRange=n;
+ for(int i=n-1; i>=0; --i)
+ if(digit[i]!=0)
+ break;
+ else
+ --firstInZeroRange;
+ int representableDigits=std::numeric_limits<double>::digits/bits;
+ int lastInRepresentableRange=0;
+ if(representableDigits<firstInZeroRange)
+ lastInRepresentableRange=firstInZeroRange-representableDigits;
+ double val=0;
+ for(int i=firstInZeroRange-1; i>=lastInRepresentableRange; --i)
+ val =val*(1<<bits)+digit[i];
+ return val*(1<<(bits*lastInRepresentableRange));
+ }
+ // print
+ template<int k>
+ inline void bigunsignedint<k>::print (std::ostream& s) const
+ {
+ bool leading=false;
+
+ // print from left to right
+ for (int i=n-1; i>=0; i--)
+ for (int d=hexdigits-1; d>=0; d--)
+ {
+ // extract one hex digit
+ int current = (digit[i]>>(d*4))&0xF;
+ if (current!=0)
+ {
+ // s.setf(std::ios::noshowbase);
+ s << std::hex << current;
+ leading = false;
+ }
+ else if (!leading) s << std::hex << current;
+ }
+ if (leading) s << "0";
+ s << std::dec;
+ }
+
+ template <int k>
+ inline std::ostream& operator<< (std::ostream& s, const bigunsignedint<k>& x)
+ {
+ x.print(s);
+ return s;
+ }
+
+
+ // Operators
+ template <int k>
+ inline bigunsignedint<k> bigunsignedint<k>::operator+ (const bigunsignedint<k>& x) const
+ {
+ bigunsignedint<k> result;
+ int overflow=0;
+
+ for (unsigned int i=0; i<n; i++)
+ {
+ int sum = ((int)digit[i]) + ((int)x.digit[i]) + overflow;
+ result.digit[i] = sum&bitmask;
+ overflow = (sum>>bits)&overflowmask;
+ }
+ return result;
+ }
+
+ template <int k>
+ inline bigunsignedint<k> bigunsignedint<k>::operator- (const bigunsignedint<k>& x) const
+ {
+ bigunsignedint<k> result;
+ int overflow=0;
+
+ for (unsigned int i=0; i<n; i++)
+ {
+ int diff = ((int)digit[i]) - (((int)x.digit[i]) + overflow);
+ if (diff>=0)
+ result.digit[i] = (unsigned short) diff;
+ else
+ {
+ result.digit[i] = (unsigned short) (diff+bitmask);
+ overflow = 1;
+ }
+ }
+ return result;
+ }
+
+ template <int k>
+ inline bigunsignedint<k> bigunsignedint<k>::operator* (const bigunsignedint<k>& x) const
+ {
+ bigunsignedint<2*k> finalproduct(0);
+
+ for (unsigned int m=0; m<n; m++) // digit in right factor
+ {
+ bigunsignedint<2*k> singleproduct(0);
+ unsigned int overflow(0);
+ for (unsigned int i=0; i<n; i++)
+ {
+ unsigned int digitproduct = ((unsigned int)digit[i])*((unsigned int)x.digit[m])+overflow;
+ singleproduct.digit[i+m] = (unsigned short) (digitproduct&bitmask);
+ overflow = (digitproduct>>bits)&bitmask;
+ }
+ finalproduct = finalproduct+singleproduct;
+ }
+
+ bigunsignedint<k> result;
+ for (unsigned int i=0; i<n; i++) result.digit[i] = finalproduct.digit[i];
+ return result;
+ }
+
+ template <int k>
+ inline bigunsignedint<k>& bigunsignedint<k>::operator++ ()
+ {
+ int overflow=1;
+
+ for (unsigned int i=0; i<n; i++)
+ {
+ int sum = ((int)digit[i]) + overflow;
+ digit[i] = sum&bitmask;
+ overflow = (sum>>bits)&overflowmask;
+ }
+ return *this;
+ }
+
+ template <int k>
+ inline bigunsignedint<k> bigunsignedint<k>::operator/ (const bigunsignedint<k>& x) const
+ {
+ if(x==0)
+ DUNE_THROW(Dune::MathError, "division by zero!");
+
+ // better slow than nothing
+ bigunsignedint<k> temp(*this);
+ bigunsignedint<k> result(0);
+
+ while (temp>=x)
+ {
+ ++result;
+ temp = temp-x;
+ }
+
+ return result;
+ }
+
+ template <int k>
+ inline bigunsignedint<k> bigunsignedint<k>::operator% (const bigunsignedint<k>& x) const
+ {
+ // better slow than nothing
+ bigunsignedint<k> temp(*this);
+ bigunsignedint<k> result(0);
+
+ while (temp>=x)
+ {
+ ++result;
+ temp = temp-x;
+ }
+
+ return temp;
+ }
+
+
+ template <int k>
+ inline bigunsignedint<k> bigunsignedint<k>::operator& (const bigunsignedint<k>& x) const
+ {
+ bigunsignedint<k> result;
+ for (unsigned int i=0; i<n; i++)
+ result.digit[i] = digit[i]&x.digit[i];
+ return result;
+ }
+
+ template <int k>
+ inline bigunsignedint<k> bigunsignedint<k>::operator^ (const bigunsignedint<k>& x) const
+ {
+ bigunsignedint<k> result;
+ for (unsigned int i=0; i<n; i++)
+ result.digit[i] = digit[i]^x.digit[i];
+ return result;
+ }
+
+ template <int k>
+ inline bigunsignedint<k> bigunsignedint<k>::operator| (const bigunsignedint<k>& x) const
+ {
+ bigunsignedint<k> result;
+ for (unsigned int i=0; i<n; i++)
+ result.digit[i] = digit[i]|x.digit[i];
+ return result;
+ }
+
+ template <int k>
+ inline bigunsignedint<k> bigunsignedint<k>::operator~ () const
+ {
+ bigunsignedint<k> result;
+ for (unsigned int i=0; i<n; i++)
+ result.digit[i] = ~digit[i];
+ return result;
+ }
+
+ template <int k>
+ inline bigunsignedint<k> bigunsignedint<k>::operator<< (int shift) const
+ {
+ bigunsignedint<k> result(0);
+
+ // multiples of bits
+ int j=shift/bits;
+ for (int i=n-1-j; i>=0; i--)
+ result.digit[i+j] = digit[i];
+
+ // remainder
+ j=shift%bits;
+ for (int i=n-1; i>=0; i--)
+ {
+ unsigned int temp = result.digit[i];
+ temp = temp<<j;
+ result.digit[i] = (unsigned short) (temp&bitmask);
+ temp = temp>>bits;
+ if (i+1<(int)n)
+ result.digit[i+1] = result.digit[i+1]|temp;
+ }
+
+ return result;
+ }
+
+ template <int k>
+ inline bigunsignedint<k> bigunsignedint<k>::operator>> (int shift) const
+ {
+ bigunsignedint<k> result(0);
+
+ // multiples of bits
+ int j=shift/bits;
+ for (unsigned int i=0; i<n-j; i++)
+ result.digit[i] = digit[i+j];
+
+ // remainder
+ j=shift%bits;
+ for (unsigned int i=0; i<n; i++)
+ {
+ unsigned int temp = result.digit[i];
+ temp = temp<<(bits-j);
+ result.digit[i] = (unsigned short) ((temp&compbitmask)>>bits);
+ if (i>0)
+ result.digit[i-1] = result.digit[i-1] | (temp&bitmask);
+ }
+
+ return result;
+ }
+
+ template <int k>
+ inline bool bigunsignedint<k>::operator!= (const bigunsignedint<k>& x) const
+ {
+ for (unsigned int i=0; i<n; i++)
+ if (digit[i]!=x.digit[i]) return true;
+ return false;
+ }
+
+ template <int k>
+ inline bool bigunsignedint<k>::operator== (const bigunsignedint<k>& x) const
+ {
+ return !((*this)!=x);
+ }
+
+ template <int k>
+ inline bool bigunsignedint<k>::operator< (const bigunsignedint<k>& x) const
+ {
+ for (int i=n-1; i>=0; i--)
+ if (digit[i]<x.digit[i]) return true;
+ else if (digit[i]>x.digit[i]) return false;
+ return false;
+ }
+
+ template <int k>
+ inline bool bigunsignedint<k>::operator<= (const bigunsignedint<k>& x) const
+ {
+ for (int i=n-1; i>=0; i--)
+ if (digit[i]<x.digit[i]) return true;
+ else if (digit[i]>x.digit[i]) return false;
+ return true;
+ }
+
+ template <int k>
+ inline bool bigunsignedint<k>::operator> (const bigunsignedint<k>& x) const
+ {
+ return !((*this)<=x);
+ }
+
+ template <int k>
+ inline bool bigunsignedint<k>::operator>= (const bigunsignedint<k>& x) const
+ {
+ return !((*this)<x);
+ }
+
+
+ template <int k>
+ inline bigunsignedint<k> operator+ (const bigunsignedint<k>& x, std::size_t y)
+ {
+ bigunsignedint<k> temp(y);
+ return x+temp;
+ }
+
+ template <int k>
+ inline bigunsignedint<k> operator- (const bigunsignedint<k>& x, std::size_t y)
+ {
+ bigunsignedint<k> temp(y);
+ return x-temp;
+ }
+
+ template <int k>
+ inline bigunsignedint<k> operator* (const bigunsignedint<k>& x, std::size_t y)
+ {
+ bigunsignedint<k> temp(y);
+ return x*temp;
+ }
+
+ template <int k>
+ inline bigunsignedint<k> operator/ (const bigunsignedint<k>& x, std::size_t y)
+ {
+ bigunsignedint<k> temp(y);
+ return x/temp;
+ }
+
+ template <int k>
+ inline bigunsignedint<k> operator% (const bigunsignedint<k>& x, std::size_t y)
+ {
+ bigunsignedint<k> temp(y);
+ return x%temp;
+ }
+
+ template <int k>
+ inline bigunsignedint<k> operator+ (std::size_t x, const bigunsignedint<k>& y)
+ {
+ bigunsignedint<k> temp(x);
+ return temp+y;
+ }
+
+ template <int k>
+ inline bigunsignedint<k> operator- (std::size_t x, const bigunsignedint<k>& y)
+ {
+ bigunsignedint<k> temp(x);
+ return temp-y;
+ }
+
+ template <int k>
+ inline bigunsignedint<k> operator* (std::size_t x, const bigunsignedint<k>& y)
+ {
+ bigunsignedint<k> temp(x);
+ return temp*y;
+ }
+
+ template <int k>
+ inline bigunsignedint<k> operator/ (std::size_t x, const bigunsignedint<k>& y)
+ {
+ bigunsignedint<k> temp(x);
+ return temp/y;
+ }
+
+ template <int k>
+ inline bigunsignedint<k> operator% (std::size_t x, const bigunsignedint<k>& y)
+ {
+ bigunsignedint<k> temp(x);
+ return temp%y;
+ }
+
+
+ /** @} */
+}
+
+namespace std
+{
+ template<int k>
+ struct numeric_limits<Dune::bigunsignedint<k> >
+ {
+ public:
+ static const bool is_specialized = true;
+
+ static Dune::bigunsignedint<k> min()
+ {
+ return static_cast<Dune::bigunsignedint<k> >(0);
+ }
+
+ static Dune::bigunsignedint<k> max()
+ {
+ Dune::bigunsignedint<k> max_;
+ for(std::size_t i=0; i < Dune::bigunsignedint<k>::n; ++i)
+ max_.digit[i]=std::numeric_limits<unsigned short>::max();
+ return max_;
+ }
+
+
+ static const int digits = Dune::bigunsignedint<k>::bits *
+ Dune::bigunsignedint<k>::n;
+ static const bool is_signed = false;
+ static const bool is_integer = true;
+ static const bool is_exact = true;
+ static const int radix = 2;
+
+ static Dune::bigunsignedint<k> epsilon()
+ {
+ return static_cast<Dune::bigunsignedint<k> >(0);
+ }
+
+ static Dune::bigunsignedint<k> round_error()
+ {
+ return static_cast<Dune::bigunsignedint<k> >(0);
+ }
+
+ static const int min_exponent = 0;
+ static const int min_exponent10 = 0;
+ static const int max_exponent = 0;
+ static const int max_exponent10 = 0;
+
+ static const bool has_infinity = false;
+ static const bool has_quiet_NaN = false;
+ static const bool has_signaling_NaN = false;
+
+ static const float_denorm_style has_denorm = denorm_absent;
+ static const bool has_denorm_loss = false;
+
+ static Dune::bigunsignedint<k> infinity() throw()
+ {
+ return static_cast<Dune::bigunsignedint<k> >(0);
+ }
+
+ static Dune::bigunsignedint<k> quiet_NaN() throw()
+ {
+ return static_cast<Dune::bigunsignedint<k> >(0);
+ }
+
+ static Dune::bigunsignedint<k> signaling_NaN() throw()
+ {
+ return static_cast<Dune::bigunsignedint<k> >(0);
+ }
+
+ static Dune::bigunsignedint<k> denorm_min() throw()
+ {
+ return static_cast<Dune::bigunsignedint<k> >(0);
+ }
+
+ static const bool is_iec559 = false;
+ static const bool is_bounded = true;
+ static const bool is_modulo = true;
+
+ static const bool traps = false;
+ static const bool tinyness_before = false;
+ static const float_round_style round_style = round_toward_zero;
+
+ };
+
+}
+
+DUNE_DEFINE_HASH(DUNE_HASH_TEMPLATE_ARGS(int k),DUNE_HASH_TYPE(Dune::bigunsignedint<k>))
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_BINARYFUNCTIONS_HH
+#define DUNE_BINARYFUNCTIONS_HH
+
+/** \file
+ * \brief Various helper classes derived from from std::binary_function for
+ * stl-style functional programming
+ */
+#include <functional>
+#include <algorithm>
+
+namespace Dune
+{
+ template<typename Type>
+ struct Min
+ : std::binary_function<Type,Type,Type>
+ {
+ Type operator()(const Type& t1, const Type& t2) const
+ {
+ return std::min(t1,t2);
+ }
+ };
+
+ template<typename Type>
+ struct Max
+ : std::binary_function<Type,Type,Type>
+ {
+ Type operator()(const Type& t1, const Type& t2) const
+ {
+ return std::max(t1,t2);
+ }
+ };
+}
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_BLOCK_BITFIELD_HH
+#define DUNE_BLOCK_BITFIELD_HH
+
+/** \file
+ \brief Efficient implementation of a dynamic array of static arrays of booleans
+ */
+
+#include <vector>
+#include <bitset>
+#include <iostream>
+#include <algorithm>
+
+#include <dune/common/genericiterator.hh>
+#include <dune/common/exceptions.hh>
+
+namespace Dune {
+
+ template <int block_size, class Alloc> class BitSetVector;
+ template <int block_size, class Alloc> class BitSetVectorReference;
+
+ /**
+ \brief A proxy class that acts as a const reference to a single
+ bitset in a BitSetVector.
+
+ It contains a conversion to std::bitset and most of the
+ interface of const std::bitset.
+
+ \warning As this is only a proxy class, you can not get the
+ address of the bitset.
+ */
+ template <int block_size, class Alloc>
+ class BitSetVectorConstReference
+ {
+ protected:
+
+ typedef Dune::BitSetVector<block_size, Alloc> BitSetVector;
+ friend class Dune::BitSetVector<block_size, Alloc>;
+
+ BitSetVectorConstReference(const BitSetVector& blockBitField, int block_number) :
+ blockBitField(blockBitField),
+ block_number(block_number)
+ {};
+
+ //! hide assignment operator
+ BitSetVectorConstReference& operator=(const BitSetVectorConstReference & b);
+
+ public:
+
+ typedef std::bitset<block_size> bitset;
+
+ // bitset interface typedefs
+ typedef typename std::vector<bool, Alloc>::const_reference reference;
+ typedef typename std::vector<bool, Alloc>::const_reference const_reference;
+ typedef size_t size_type;
+
+ //! Returns a copy of *this shifted left by n bits.
+ bitset operator<<(size_type n) const
+ {
+ bitset b = *this;
+ b <<= n;
+ return b;
+ }
+
+ //! Returns a copy of *this shifted right by n bits.
+ bitset operator>>(size_type n) const
+ {
+ bitset b = *this;
+ b >>= n;
+ return b;
+ }
+
+ //! Returns a copy of *this with all of its bits flipped.
+ bitset operator~() const
+ {
+ bitset b = *this;
+ b.flip();
+ return b;
+ }
+
+ //! Returns block_size.
+ size_type size() const
+ {
+ return block_size;
+ }
+
+ //! Returns the number of bits that are set.
+ size_type count() const
+ {
+ size_type n = 0;
+ for(size_type i=0; i<block_size; ++i)
+ n += getBit(i);
+ return n;
+ }
+
+ //! Returns true if any bits are set.
+ bool any() const
+ {
+ return count();
+ }
+
+ //! Returns true if no bits are set.
+ bool none() const
+ {
+ return ! any();
+ }
+
+ //! Returns true if bit n is set.
+ bool test(size_type n) const
+ {
+ return getBit(n);
+ }
+
+ const_reference operator[](size_type i) const
+ {
+ return getBit(i);
+ }
+
+ //! cast to bitset
+ operator bitset() const
+ {
+ return blockBitField.getRepr(block_number);
+ }
+
+ //! Equality of reference and std::bitset
+ bool operator== (const bitset& bs) const
+ {
+ return equals(bs);
+ }
+
+ //! Equality of reference and other reference
+ bool operator== (const BitSetVectorConstReference& bs) const
+ {
+ return equals(bs);
+ }
+
+ //! Inequality of reference and std::bitset
+ bool operator!= (const bitset& bs) const
+ {
+ return ! equals(bs);
+ }
+
+ //! Inequality of reference and other reference
+ bool operator!= (const BitSetVectorConstReference& bs) const
+ {
+ return ! equals(bs);
+ }
+
+ /*!
+ missing operators:
+
+ - unsigned long to_ulong() const
+ */
+
+ friend std::ostream& operator<< (std::ostream& s, const BitSetVectorConstReference& v)
+ {
+ s << "(";
+ for(int i=0; i<block_size; ++i)
+ s << v[i];
+ s << ")";
+ return s;
+ }
+
+ protected:
+ const BitSetVector& blockBitField;
+ int block_number;
+
+ const_reference getBit(size_type i) const
+ {
+ return blockBitField.getBit(block_number,i);
+ }
+
+ template<class BS>
+ bool equals(const BS & bs) const
+ {
+ bool eq = true;
+ for(int i=0; i<block_size; ++i)
+ eq &= (getBit(i) == bs[i]);
+ return eq;
+ }
+
+ private:
+ /**
+ This is only a Proxy class, you can't get the address of the
+ object it references
+ */
+ void operator & ();
+
+ friend class BitSetVectorReference<block_size, Alloc>;
+ };
+
+ /**
+ \brief A proxy class that acts as a mutable reference to a
+ single bitset in a BitSetVector.
+
+ It contains an assignment operator from std::bitset. It
+ inherits the const std::bitset interface provided by
+ BitSetVectorConstReference and adds most of the non-const
+ methods of std::bitset.
+
+ \warning As this is only a proxy class, you can not get the
+ address of the bitset.
+ */
+ template <int block_size, class Alloc>
+ class BitSetVectorReference : public BitSetVectorConstReference<block_size,Alloc>
+ {
+ protected:
+
+ typedef Dune::BitSetVector<block_size, Alloc> BitSetVector;
+ friend class Dune::BitSetVector<block_size, Alloc>;
+
+ typedef Dune::BitSetVectorConstReference<block_size,Alloc> BitSetVectorConstReference;
+
+ BitSetVectorReference(BitSetVector& blockBitField, int block_number) :
+ BitSetVectorConstReference(blockBitField, block_number),
+ blockBitField(blockBitField)
+ {};
+
+ public:
+ typedef std::bitset<block_size> bitset;
+
+ //! bitset interface typedefs
+ //! \{
+ //! A proxy class that acts as a reference to a single bit.
+ typedef typename std::vector<bool, Alloc>::reference reference;
+ //! A proxy class that acts as a const reference to a single bit.
+ typedef typename std::vector<bool, Alloc>::const_reference const_reference;
+ //! \}
+
+ //! size_type typedef (an unsigned integral type)
+ typedef size_t size_type;
+
+ //! Assignment from bool, sets each bit in the bitset to b
+ BitSetVectorReference& operator=(bool b)
+ {
+ for(int i=0; i<block_size; ++i)
+ getBit(i) = b;
+ return (*this);
+ }
+
+ //! Assignment from bitset
+ BitSetVectorReference& operator=(const bitset & b)
+ {
+ for(int i=0; i<block_size; ++i)
+ getBit(i) = b.test(i);
+ return (*this);
+ }
+
+ //! Assignment from BitSetVectorConstReference
+ BitSetVectorReference& operator=(const BitSetVectorConstReference & b)
+ {
+ for(int i=0; i<block_size; ++i)
+ getBit(i) = b.test(i);
+ return (*this);
+ }
+
+ //! Assignment from BitSetVectorReference
+ BitSetVectorReference& operator=(const BitSetVectorReference & b)
+ {
+ for(int i=0; i<block_size; ++i)
+ getBit(i) = b.test(i);
+ return (*this);
+ }
+
+ //! Bitwise and (for bitset).
+ BitSetVectorReference& operator&=(const bitset& x)
+ {
+ for (size_type i=0; i<block_size; i++)
+ getBit(i) = (test(i) & x.test(i));
+ return *this;
+ }
+
+ //! Bitwise and (for BitSetVectorConstReference and BitSetVectorReference)
+ BitSetVectorReference& operator&=(const BitSetVectorConstReference& x)
+ {
+ for (size_type i=0; i<block_size; i++)
+ getBit(i) = (test(i) & x.test(i));
+ return *this;
+ }
+
+ //! Bitwise inclusive or (for bitset)
+ BitSetVectorReference& operator|=(const bitset& x)
+ {
+ for (size_type i=0; i<block_size; i++)
+ getBit(i) = (test(i) | x.test(i));
+ return *this;
+ }
+
+ //! Bitwise inclusive or (for BitSetVectorConstReference and BitSetVectorReference)
+ BitSetVectorReference& operator|=(const BitSetVectorConstReference& x)
+ {
+ for (size_type i=0; i<block_size; i++)
+ getBit(i) = (test(i) | x.test(i));
+ return *this;
+ }
+
+ //! Bitwise exclusive or (for bitset).
+ BitSetVectorReference& operator^=(const bitset& x)
+ {
+ for (size_type i=0; i<block_size; i++)
+ getBit(i) = (test(i) ^ x.test(i));
+ return *this;
+ }
+
+ //! Bitwise exclusive or (for BitSetVectorConstReference and BitSetVectorReference)
+ BitSetVectorReference& operator^=(const BitSetVectorConstReference& x)
+ {
+ for (size_type i=0; i<block_size; i++)
+ getBit(i) = (test(i) ^ x.test(i));
+ return *this;
+ }
+
+ //! Left shift.
+ BitSetVectorReference& operator<<=(size_type n)
+ {
+ for (size_type i=0; i<block_size-n; i++)
+ getBit(i) = test(i+n);
+ return *this;
+ }
+
+ //! Right shift.
+ BitSetVectorReference& operator>>=(size_type n)
+ {
+ for (size_type i=0; i<block_size-n; i++)
+ getBit(i+n) = test(i);
+ return *this;
+ }
+
+ // Sets every bit.
+ BitSetVectorReference& set()
+ {
+ for (size_type i=0; i<block_size; i++)
+ set(i);
+ return *this;
+ }
+
+ //! Flips the value of every bit.
+ BitSetVectorReference& flip()
+ {
+ for (size_type i=0; i<block_size; i++)
+ flip(i);
+ return *this;
+ }
+
+ //! Clears every bit.
+ BitSetVectorReference& reset()
+ {}
+
+ //! Sets bit n if val is nonzero, and clears bit n if val is zero.
+ BitSetVectorReference& set(size_type n, int val = 1)
+ {
+ getBit(n) = val;
+ return *this;
+ }
+
+ //! Clears bit n.
+ BitSetVectorReference& reset(size_type n)
+ {
+ set(n, false);
+ return *this;
+ }
+
+ //! Flips bit n.
+ BitSetVectorReference& flip(size_type n)
+ {
+ getBit(n).flip();
+ return *this;
+ }
+
+ using BitSetVectorConstReference::test;
+ using BitSetVectorConstReference::operator[];
+
+ reference operator[](size_type i)
+ {
+ return getBit(i);
+ }
+
+ protected:
+ BitSetVector& blockBitField;
+
+ using BitSetVectorConstReference::getBit;
+
+ reference getBit(size_type i)
+ {
+ return blockBitField.getBit(this->block_number,i);
+ }
+ };
+
+ /**
+ typetraits for BitSetVectorReference
+ */
+ template<int block_size, class Alloc>
+ struct const_reference< BitSetVectorReference<block_size,Alloc> >
+ {
+ typedef BitSetVectorConstReference<block_size,Alloc> type;
+ };
+
+ template<int block_size, class Alloc>
+ struct const_reference< BitSetVectorConstReference<block_size,Alloc> >
+ {
+ typedef BitSetVectorConstReference<block_size,Alloc> type;
+ };
+
+ template<int block_size, class Alloc>
+ struct mutable_reference< BitSetVectorReference<block_size,Alloc> >
+ {
+ typedef BitSetVectorReference<block_size,Alloc> type;
+ };
+
+ template<int block_size, class Alloc>
+ struct mutable_reference< BitSetVectorConstReference<block_size,Alloc> >
+ {
+ typedef BitSetVectorReference<block_size,Alloc> type;
+ };
+
+ /**
+ \brief A dynamic %array of blocks of booleans
+ */
+ template <int block_size, class Allocator=std::allocator<bool> >
+ class BitSetVector : private std::vector<bool, Allocator>
+ {
+ /** \brief The implementation class: an unblocked bitfield */
+ typedef std::vector<bool, Allocator> BlocklessBaseClass;
+
+ public:
+ //! container interface typedefs
+ //! \{
+
+ /** \brief Type of the values stored by the container */
+ typedef std::bitset<block_size> value_type;
+
+ /** \brief Reference to a small block of bits */
+ typedef BitSetVectorReference<block_size,Allocator> reference;
+
+ /** \brief Const reference to a small block of bits */
+ typedef BitSetVectorConstReference<block_size,Allocator> const_reference;
+
+ /** \brief Pointer to a small block of bits */
+ typedef BitSetVectorReference<block_size,Allocator>* pointer;
+
+ /** \brief Const pointer to a small block of bits */
+ typedef BitSetVectorConstReference<block_size,Allocator>* const_pointer;
+
+ /** \brief size type */
+ typedef typename std::vector<bool, Allocator>::size_type size_type;
+
+ /** \brief The type of the allocator */
+ typedef Allocator allocator_type;
+ //! \}
+
+ //! iterators
+ //! \{
+ typedef Dune::GenericIterator<BitSetVector<block_size,Allocator>, value_type, reference, std::ptrdiff_t, ForwardIteratorFacade> iterator;
+ typedef Dune::GenericIterator<const BitSetVector<block_size,Allocator>, const value_type, const_reference, std::ptrdiff_t, ForwardIteratorFacade> const_iterator;
+ //! \}
+
+ //! Returns a iterator pointing to the beginning of the vector.
+ iterator begin(){
+ return iterator(*this, 0);
+ }
+
+ //! Returns a const_iterator pointing to the beginning of the vector.
+ const_iterator begin() const {
+ return const_iterator(*this, 0);
+ }
+
+ //! Returns an iterator pointing to the end of the vector.
+ iterator end(){
+ return iterator(*this, size());
+ }
+
+ //! Returns a const_iterator pointing to the end of the vector.
+ const_iterator end() const {
+ return const_iterator(*this, size());
+ }
+
+ //! Default constructor
+ BitSetVector() :
+ BlocklessBaseClass()
+ {}
+
+ //! Construction from an unblocked bitfield
+ BitSetVector(const BlocklessBaseClass& blocklessBitField) :
+ BlocklessBaseClass(blocklessBitField)
+ {
+ if (blocklessBitField.size()%block_size != 0)
+ DUNE_THROW(RangeError, "Vector size is not a multiple of the block size!");
+ }
+
+ /** Constructor with a given length
+ \param n Number of blocks
+ */
+ explicit BitSetVector(int n) :
+ BlocklessBaseClass(n*block_size)
+ {}
+
+ //! Constructor which initializes the field with true or false
+ BitSetVector(int n, bool v) :
+ BlocklessBaseClass(n*block_size,v)
+ {}
+
+ //! Erases all of the elements.
+ void clear()
+ {
+ BlocklessBaseClass::clear();
+ }
+
+ //! Resize field
+ void resize(int n, bool v = bool())
+ {
+ BlocklessBaseClass::resize(n*block_size, v);
+ }
+
+ /** \brief Return the number of blocks */
+ size_type size() const
+ {
+ return BlocklessBaseClass::size()/block_size;
+ }
+
+ //! Sets all entries to <tt> true </tt>
+ void setAll() {
+ this->assign(BlocklessBaseClass::size(), true);
+ }
+
+ //! Sets all entries to <tt> false </tt>
+ void unsetAll() {
+ this->assign(BlocklessBaseClass::size(), false);
+ }
+
+ /** \brief Return reference to i-th block */
+ reference operator[](int i)
+ {
+ return reference(*this, i);
+ }
+
+ /** \brief Return const reference to i-th block */
+ const_reference operator[](int i) const
+ {
+ return const_reference(*this, i);
+ }
+
+ /** \brief Return reference to last block */
+ reference back()
+ {
+ return reference(*this, size()-1);
+ }
+
+ /** \brief Return const reference to last block */
+ const_reference back() const
+ {
+ return const_reference(*this, size()-1);
+ }
+
+ //! Returns the number of bits that are set.
+ size_type count() const
+ {
+ return std::count(BlocklessBaseClass::begin(), BlocklessBaseClass::end(), true);
+ }
+
+ //! Returns the number of set bits, while each block is masked with 1<<i
+ size_type countmasked(int j) const
+ {
+ size_type n = 0;
+ size_type blocks = size();
+ for(size_type i=0; i<blocks; ++i)
+ n += getBit(i,j);
+ return n;
+ }
+
+ //! Send bitfield to an output stream
+ friend std::ostream& operator<< (std::ostream& s, const BitSetVector& v)
+ {
+ for (size_t i=0; i<v.size(); i++)
+ s << v[i] << " ";
+ return s;
+ }
+
+ private:
+
+ // get a prepresentation as value_type
+ value_type getRepr(int i) const
+ {
+ value_type bits;
+ for(int j=0; j<block_size; ++j)
+ bits.set(j, getBit(i,j));
+ return bits;
+ }
+
+ typename std::vector<bool>::reference getBit(size_type i, size_type j) {
+ return BlocklessBaseClass::operator[](i*block_size+j);
+ }
+
+ typename std::vector<bool>::const_reference getBit(size_type i, size_type j) const {
+ return BlocklessBaseClass::operator[](i*block_size+j);
+ }
+
+ friend class BitSetVectorReference<block_size,Allocator>;
+ friend class BitSetVectorConstReference<block_size,Allocator>;
+ };
+
+} // namespace Dune
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_CLASSNAME_HH
+#define DUNE_CLASSNAME_HH
+
+/** \file
+ * \brief A free function to provide the demangled class name
+ * of a given object or type as a string
+ */
+
+#include <cstdlib>
+#include <string>
+#include <typeinfo>
+
+#if HAVE_CXA_DEMANGLE
+#include <cxxabi.h>
+#endif // #if HAVE_CXA_DEMANGLE
+
+namespace Dune {
+
+ /** \brief Provide the demangled class name of a given object as a string */
+ template <class T>
+ std::string className ( T &t )
+ {
+ std::string className = typeid( t ).name();
+#if HAVE_CXA_DEMANGLE
+ int status;
+ char *demangled = abi::__cxa_demangle( className.c_str(), 0, 0, &status );
+ if( demangled )
+ {
+ className = demangled;
+ std::free( demangled );
+ }
+#endif // #if HAVE_CXA_DEMANGLE
+ return className;
+ }
+
+ /** \brief Provide the demangled class name of a type T as a string */
+ template <class T>
+ std::string className ()
+ {
+ std::string className = typeid( T ).name();
+#if HAVE_CXA_DEMANGLE
+ int status;
+ char *demangled = abi::__cxa_demangle( className.c_str(), 0, 0, &status );
+ if( demangled )
+ {
+ className = demangled;
+ std::free( demangled );
+ }
+#endif // #if HAVE_CXA_DEMANGLE
+ return className;
+ }
+
+} // namespace Dune
+
+#endif // DUNE_CLASSNAME_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_COLLECTIVECOMMUNICATION_HH
+#warning dune/common/collectivecommunication.hh is deprecated, please use dune/common/parallel/collectivecommunication.hh
+#include "parallel/collectivecommunication.hh"
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "debugallocator.hh"
+
+#include <iostream>
+#include <unistd.h>
+#include <cstdlib>
+
+namespace Dune
+{
+ namespace DebugMemory
+ {
+ // system constant for page size
+ const std::ptrdiff_t page_size = getpagesize();
+
+ // implement member functions
+ void AllocationManager::allocation_error(const char* msg)
+ {
+ std::cerr << "Abort - Memory Corruption: " << msg << std::endl;
+ std::abort();
+ }
+
+ // global instance of AllocationManager
+ AllocationManager alloc_man;
+
+ } // end namespace DebugMemory
+} // end namespace Dune
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_DEBUG_ALLOCATOR_HH
+#define DUNE_DEBUG_ALLOCATOR_HH
+
+#include <dune/common/unused.hh>
+#include <exception>
+#include <typeinfo>
+#include <vector>
+#include <iostream>
+#include <cstring>
+#include <cstdlib>
+#include <new>
+#if HAVE_SYS_MMAN_H and HAVE_MPROTECT
+#include <sys/mman.h>
+#else
+enum DummyProtFlags { PROT_NONE, PROT_WRITE, PROT_READ };
+#endif
+
+#include "mallocallocator.hh"
+
+namespace Dune
+{
+
+#ifndef DOXYGEN // hide implementation details from doxygen
+ namespace DebugMemory
+ {
+
+ extern const std::ptrdiff_t page_size;
+
+ struct AllocationManager
+ {
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef void* pointer;
+
+ protected:
+ static void allocation_error(const char* msg);
+
+ struct AllocationInfo;
+ friend struct AllocationInfo;
+
+#define ALLOCATION_ASSERT(A) { if (!(A)) \
+ { allocation_error("Assertion " # A " failed");\
+ }\
+};
+
+ struct AllocationInfo
+ {
+ AllocationInfo(const std::type_info & t) : type(&t) {}
+ const std::type_info * type;
+
+ pointer page_ptr;
+ pointer ptr;
+ size_type pages;
+ size_type capacity;
+ size_type size;
+ bool not_free;
+ };
+
+ typedef MallocAllocator<AllocationInfo> Alloc;
+ typedef std::vector<AllocationInfo, Alloc> AllocationList;
+ AllocationList allocation_list;
+
+ private:
+ void memprotect(void* from, difference_type len, int prot)
+ {
+#if HAVE_SYS_MMAN_H and HAVE_MPROTECT
+ int result = mprotect(from, len, prot);
+ if (result == -1)
+ {
+
+ std::cerr << "ERROR: (" << result << ": " << strerror(result) << ")" << std::endl;
+ std::cerr << " Failed to ";
+ if (prot == PROT_NONE)
+ std::cerr << "protect ";
+ else
+ std::cerr << "unprotect ";
+ std::cerr << "memory range: "
+ << from << ", "
+ << static_cast<void*>(
+ static_cast<char*>(from) + len)
+ << std::endl;
+ abort();
+ }
+#else
+ DUNE_UNUSED_PARAMETER(from);
+ DUNE_UNUSED_PARAMETER(len);
+ DUNE_UNUSED_PARAMETER(prot);
+ std::cerr << "WARNING: memory protection not available" << std::endl;
+#endif
+ }
+
+ public:
+
+ ~AllocationManager ()
+ {
+ AllocationList::iterator it;
+ bool error = false;
+ for (it=allocation_list.begin(); it!=allocation_list.end(); it++)
+ {
+ if (it->not_free)
+ {
+ std::cerr << "ERROR: found memory chunk still in use: " <<
+ it->capacity << " bytes at " << it->ptr << std::endl;
+ error = true;
+ }
+ free(it->page_ptr);
+ }
+ if (error)
+ allocation_error("lost allocations");
+ }
+
+ template<typename T>
+ T* allocate(size_type n) throw(std::bad_alloc)
+ {
+ // setup chunk info
+ AllocationInfo ai(typeid(T));
+ ai.size = n;
+ ai.capacity = n * sizeof(T);
+ ai.pages = (ai.capacity) / page_size + 2;
+ ai.not_free = true;
+ size_type overlap = ai.capacity % page_size;
+ int result = posix_memalign(&(ai.page_ptr), page_size, ai.pages * page_size);
+ if (0 != result)
+ {
+ throw std::bad_alloc();
+ }
+ ai.ptr = static_cast<char*>(ai.page_ptr) + page_size - overlap;
+ // write protect memory behind the actual data
+ memprotect(static_cast<char*>(ai.page_ptr) + (ai.pages-1) * page_size,
+ page_size,
+ PROT_NONE);
+ // remember the chunk
+ allocation_list.push_back(ai);
+ // return the ptr
+ return static_cast<T*>(ai.ptr);
+ }
+
+ template<typename T>
+ void deallocate(T* ptr, size_type n = 0) throw()
+ {
+ // compute page address
+ void* page_ptr =
+ static_cast<void*>(
+ (char*)(ptr) - ((difference_type)(ptr) % page_size));
+ // search list
+ AllocationList::iterator it;
+ unsigned int i = 0;
+ for (it=allocation_list.begin(); it!=allocation_list.end(); it++, i++)
+ {
+ if (it->page_ptr == page_ptr)
+ {
+ // std::cout << "found memory_block in allocation " << i << std::endl;
+ // sanity checks
+ if (n != 0)
+ ALLOCATION_ASSERT(n == it->size);
+ ALLOCATION_ASSERT(ptr == it->ptr);
+ ALLOCATION_ASSERT(true == it->not_free);
+ ALLOCATION_ASSERT(typeid(T) == *(it->type));
+ // free memory
+ it->not_free = false;
+#if DEBUG_ALLOCATOR_KEEP
+ // write protect old memory
+ memprotect(it->page_ptr,
+ (it->pages) * page_size,
+ PROT_NONE);
+#else
+ // unprotect old memory
+ memprotect(it->page_ptr,
+ (it->pages) * page_size,
+ PROT_READ | PROT_WRITE);
+ std::free(it->page_ptr);
+ // remove chunk info
+ allocation_list.erase(it);
+#endif
+ return;
+ }
+ }
+ allocation_error("memory block not found");
+ }
+ };
+#undef ALLOCATION_ASSERT
+
+ extern AllocationManager alloc_man;
+ } // end namespace DebugMemory
+#endif // DOXYGEN
+
+ template<class T>
+ class DebugAllocator;
+
+ // specialize for void
+ template <>
+ class DebugAllocator<void> {
+ public:
+ typedef void* pointer;
+ typedef const void* const_pointer;
+ // reference to void members are impossible.
+ typedef void value_type;
+ template <class U> struct rebind {
+ typedef DebugAllocator<U> other;
+ };
+ };
+
+ // actual implementation
+ /**
+ @ingroup Allocators
+ @brief Allocators implementation which performs different kind of memory checks
+
+ We check:
+ - access past the end
+ - only free memory which was allocated with this allocator
+ - list allocated memory chunks still in use upon destruction of the allocator
+
+ When defining DEBUG_ALLOCATOR_KEEP to 1, we also check
+ - double free
+ - access after free
+
+ When defining DEBUG_NEW_DELETE >= 1, we
+ - overload new/delte
+ - use the Debug memory management for new/delete
+ - DEBUG_NEW_DELETE > 2 gives extensive debug output
+ */
+ template <class T>
+ class DebugAllocator {
+ public:
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T value_type;
+ template <class U> struct rebind {
+ typedef DebugAllocator<U> other;
+ };
+
+ //! create a new DebugAllocator
+ DebugAllocator() throw() {}
+ //! copy construct from an other DebugAllocator, possibly for a different result type
+ template <class U>
+ DebugAllocator(const DebugAllocator<U>&) throw() {}
+ //! cleanup this allocator
+ ~DebugAllocator() throw() {}
+
+ pointer address(reference x) const
+ {
+ return &x;
+ }
+ const_pointer address(const_reference x) const
+ {
+ return &x;
+ }
+
+ //! allocate n objects of type T
+ pointer allocate(size_type n,
+ DebugAllocator<void>::const_pointer hint = 0)
+ {
+ DUNE_UNUSED_PARAMETER(hint);
+ return DebugMemory::alloc_man.allocate<T>(n);
+ }
+
+ //! deallocate n objects of type T at address p
+ void deallocate(pointer p, size_type n)
+ {
+ DebugMemory::alloc_man.deallocate<T>(p,n);
+ }
+
+ //! max size for allocate
+ size_type max_size() const throw()
+ {
+ return size_type(-1) / sizeof(T);
+ }
+
+ //! copy-construct an object of type T (i.e. make a placement new on p)
+ void construct(pointer p, const T& val)
+ {
+ ::new((void*)p)T(val);
+ }
+#if ( HAVE_VARIADIC_TEMPLATES && HAVE_RVALUE_REFERENCES ) || DOXYGEN
+ //! construct an object of type T from variadic parameters
+ //! \note works only with newer C++ compilers
+ template<typename ... _Args>
+ void construct(pointer p, _Args&&... __args)
+ {
+ ::new((void *)p)T(std::forward<_Args>(__args) ...);
+ }
+#endif
+ //! destroy an object of type T (i.e. call the destructor)
+ void destroy(pointer p)
+ {
+ p->~T();
+ }
+ };
+}
+
+#ifdef DEBUG_NEW_DELETE
+void * operator new(size_t size) throw(std::bad_alloc)
+{
+ // try to allocate size bytes
+ void *p = Dune::DebugMemory::alloc_man.allocate<char>(size);
+#if DEBUG_NEW_DELETE > 2
+ std::cout << "NEW " << size
+ << " -> " << p
+ << std::endl;
+#endif
+ return p;
+}
+
+void operator delete(void * p) throw()
+{
+#if DEBUG_NEW_DELETE > 2
+ std::cout << "FREE " << p << std::endl;
+#endif
+ Dune::DebugMemory::alloc_man.deallocate<char>(static_cast<char*>(p));
+}
+
+#endif // DEBUG_NEW_DELETE
+
+#endif // DUNE_DEBUG_ALLOCATOR_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+
+#ifndef DUNE_DEBUGSTREAM_HH
+#define DUNE_DEBUGSTREAM_HH
+
+/** \file
+ * \brief Defines several output streams for messages of different importance
+ */
+
+#include <iostream>
+#include <stack>
+
+#include <dune/common/exceptions.hh>
+
+namespace Dune {
+
+ /*! \defgroup DebugOut Debug output
+ \ingroup Common
+
+ The debug output is implemented by instances of DebugStream which
+ provides the following features:
+
+ - output-syntax in the standard ostream-notation
+ - output can be totally deactivated depending on template parameters
+ - streams with active output can be deactivated during runtime
+ - redirecting to std::ostream or other DebugStream s during runtime
+ - stack oriented state
+
+ The Dune-components should use the streams explained in \ref StdStreams
+ for output so that applications may redirect the output globally.
+
+ Changes in runtime are provided by three sets of methods:
+
+ - push()/pop() sets new activation flag or restore old setting
+ - attach()/detach() redirects output to a different std::ostream or restore old stream
+ - tie()/untie() redirects output through another DebugStream. If the state of the master stream changes (activation or output-stream) it is changed in the tied stream as well
+
+ The first methods implement a full stack whereas tie() is a bit
+ different: though a tied stream may be (de)activated via
+ push()/pop() you cannot attach() or detach() an output. You'll need
+ to change the master stream instead.
+
+ \section DebugAppl Applications
+
+ Applications using the Dune-library should create an independent set
+ of DebugStreams so that the debug levels can be changed separately.
+ Example:
+
+ \code
+ static const Dune::DebugLevel APPL_MINLEVEL = 3;
+
+ Dune::DebugStream<1, APPL_MINLEVEL> myverbose;
+ Dune::DebugStream<2, APPL_MINLEVEL> myinfo;
+ Dune::DebugStream<3, APPL_MINLEVEL> mywarn;
+ \endcode
+
+ This code creates three streams of which only the last one really
+ creates output. The output-routines of the other streams vanish in
+ optimized executables.
+
+ You can use the common_bits-Template to switch to a policy using bitflags:
+
+ \code
+ enum { APPL_CORE = 1, APPL_IO = 2, APPL_GRAPHICS = 4};
+
+ static const Dune::DebugLevel APPL_DEBUG_MASK = APPL_CORE | APPL_GRAPHICS;
+ static const Dune::DebugLevel APPL_ACTIVE_MASK = 0xff;
+
+ Dune::DebugStream<APPL_CORE, APPL_DEBUG_MASK, APPL_ACTIVE_MASK, Dune::common_bits> coreout;
+ Dune::DebugStream<APPL_IO, APPL_DEBUG_MASK, APPL_ACTIVE_MASK, Dune::common_bits> ioout;
+ Dune::DebugStream<APPL_GRAPHICS, APPL_DEBUG_MASK, APPL_ACTIVE_MASK, Dune::common_bits> graphout;
+ \endcode
+
+ Applications that wish to redirect the \ref StdStreams through their
+ private streams may use the tie()-mechanism:
+
+ \code
+ // initialize streams like above
+
+ Dune::dwarn.tie(coreout);
+
+ // ... Dune-output to dwarn will be directed through coreout ...
+
+ Dune::dwarn.untie();
+ \endcode
+
+ Keep in mind to untie() a stream before the tied stream is destructed.
+
+ An alternative is to attach() an output stream defined by the application:
+
+ \code
+ std::ofstream mylog("application.log");
+
+ Dune::dwarn.attach(mylog);
+ \endcode
+ */
+ /**
+ \addtogroup DebugOut
+ \{
+ */
+ /*! \file
+
+ This file implements the class DebugStream to support output in a
+ variety of debug levels. Additionally, template parameters control
+ if the output operation is really performed so that unused debug
+ levels can be deactivated
+
+ */
+
+
+ /*! \brief Type for debug levels.
+
+ Only positive values allowed
+ */
+ typedef unsigned int DebugLevel;
+
+ /*!
+
+ \brief Greater or equal template test.
+
+ value is false if current is below the threshold, true otherwise
+
+ This is the default struct to control the activation policy of
+ DebugStream and deactivates output below the threshold
+ */
+ template <DebugLevel current, DebugLevel threshold>
+ struct greater_or_equal {
+ static const bool value = (current >= threshold);
+ };
+
+
+ /*! \brief activate if current and mask have common bits switched on.
+
+ This template implements an alternative strategy to activate or
+ deactivate a DebugStream. Keep in mind to number your streams as
+ powers of two if using this template
+ */
+ template <DebugLevel current, DebugLevel mask>
+ struct common_bits {
+ enum {value = ((current & mask)!=0) };
+ };
+
+
+ //! \brief standard exception for the debugstream
+ class DebugStreamError : public IOError {};
+
+ class StreamWrap {
+ public:
+ StreamWrap(std::ostream& _out) : out(_out) { };
+ std::ostream& out;
+ StreamWrap *next;
+ };
+
+ //! \brief Intermediate class to implement tie-operation of DebugStream
+ class DebugStreamState {
+ // !!! should be protected somehow but that won't be easy
+ public:
+ //! \brief current output stream and link to possibly pushed old output streams
+ StreamWrap* current;
+
+ //! \brief flag to switch output during runtime
+ bool _active;
+
+ //! \brief are we tied to another DebugStream?
+ bool _tied;
+
+ //! \brief how many streams are tied to this state
+ unsigned int _tied_streams;
+ };
+
+ /*!
+ \brief Generic class to implement debug output streams
+
+ The main function of a DebugStream is to provide output in a
+ standard ostream fashion that is fully deactivated if the level of
+ the stream does not meet the current requirements. More information in \ref DebugOut
+
+ \param thislevel this level
+ \param dlevel level needed for any output to happen
+ \param alevel level needed to switch activation flag on
+ \param activator template describing the activation policy
+
+ \todo Fix visibility of internal data
+ */
+ template <DebugLevel thislevel = 1,
+ DebugLevel dlevel = 1,
+ DebugLevel alevel = 1,
+ template<DebugLevel, DebugLevel> class activator = greater_or_equal>
+ class DebugStream : public DebugStreamState {
+ public:
+ /*! \brief Create a DebugStream and set initial output stream
+
+ during runtime another stream can be attach()ed, however the
+ initial stream may not be detach()ed.
+ */
+ DebugStream(std::ostream& out = std::cerr) {
+ // start a new list of streams
+ current = new StreamWrap(out);
+ current->next = 0;
+
+ // check if we are above the default activation level
+ _active = activator<thislevel,alevel>::value;
+
+ // we're not tied to another DebugStream
+ _tied = false;
+
+ // no child streams yet
+ _tied_streams = 0;
+ };
+
+ /*! \brief Create a DebugStream and directly tie to another DebugStream
+
+ The fallback is used if a DebugStream constructed via this method
+ is untie()ed later. Otherwise the stream would be broken afterwards.
+ */
+ DebugStream (DebugStreamState& master,
+ std::ostream& fallback = std::cerr)
+ {
+ // start a new list of streams
+ current = new StreamWrap(fallback);
+ current->next = 0;
+
+ // check if we are above the default activation level
+ _active = activator<thislevel,alevel>::value;
+ _tied_streams = 0;
+
+ // tie to the provided stream
+ _tied = true;
+ tiedstate = &master;
+ tiedstate->_tied_streams++;
+ };
+
+ /*! \brief Destroy stream.
+
+ if other streams still tie() to this stream an exception will be
+ thrown. Otherwise the child streams would certainly break on the
+ next output
+ */
+ ~DebugStream() {
+ // untie
+ if (_tied)
+ tiedstate->_tied_streams--;
+ else {
+ // check if somebody still ties to us...
+ if (_tied_streams != 0)
+ DUNE_THROW(DebugStreamError,
+ "There are streams still tied to this stream!");
+ };
+
+ // remove ostream-stack
+ while (current != 0) {
+ StreamWrap *s = current;
+ current = current->next;
+ delete s;
+ };
+ };
+
+ //! \brief Generic types are passed on to current output stream
+ template <class T>
+ DebugStream& operator<<(const T data) {
+ // remove the following code if stream wasn't compiled active
+ if (activator<thislevel, dlevel>::value) {
+ if (! _tied) {
+ if (_active)
+ current->out << data;
+ } else {
+ if (_active && tiedstate->_active)
+ tiedstate->current->out << data;
+ };
+ };
+
+ return *this;
+ }
+
+ /*! \brief explicit specialization so that enums can be printed
+
+ Operators for built-in types follow special
+ rules (§11.2.3) so that enums won't fit into the generic
+ method above. With an existing operator<< for int however
+ the enum will be automatically casted.
+ */
+ DebugStream& operator<<(const int data) {
+ // remove the following code if stream wasn't compiled active
+ if (activator<thislevel, dlevel>::value) {
+ if (! _tied) {
+ if (_active)
+ current->out << data;
+ } else {
+ if (_active && tiedstate->_active)
+ tiedstate->current->out << data;
+ };
+ };
+
+ return *this;
+ }
+
+ //! \brief pass on manipulators to underlying output stream
+ DebugStream& operator<<(std::ostream& (*f)(std::ostream&)) {
+ if (activator<thislevel, dlevel>::value) {
+ if (! _tied) {
+ if (_active)
+ f(current->out);
+ } else {
+ if (_active && tiedstate->_active)
+ f(tiedstate->current->out);
+ };
+ }
+
+ return *this;
+ };
+
+ //! \brief pass on flush to underlying output stream
+ DebugStream& flush() {
+ if (activator<thislevel, dlevel>::value) {
+ if (! _tied) {
+ if (_active)
+ current->out.flush();
+ } else {
+ if (_active && tiedstate->_active)
+ tiedstate->current->out.flush();
+ };
+ }
+
+ return *this;
+ };
+
+ //! \brief set activation flag and store old value
+ void push(bool b) {
+ // are we at all active?
+ if (activator<thislevel,alevel>::value) {
+ _actstack.push(_active);
+ _active = b;
+ } else {
+ // stay off
+ _actstack.push(false);
+ };
+ };
+
+ //! \brief restore previously set activation flag
+ void pop() throw(DebugStreamError) {
+ if (_actstack.empty())
+ DUNE_THROW(DebugStreamError, "No previous activation setting!");
+
+ _active = _actstack.top();
+ _actstack.pop();
+ };
+
+ /*! \brief reports if this stream will produce output
+
+ a DebugStream that is deactivated because of its level will always
+ return false, otherwise the state of the internal activation is
+ returned
+ */
+ bool active() const {
+ return activator<thislevel, dlevel>::value && _active;
+ };
+
+ /*! \brief set output to a different stream.
+
+ Old stream data is stored
+ */
+ void attach(std::ostream& stream) {
+ if (_tied)
+ DUNE_THROW(DebugStreamError, "Cannot attach to a tied stream!");
+
+ StreamWrap* newcurr = new StreamWrap(stream);
+ newcurr->next = current;
+ current = newcurr;
+ };
+
+ //! \brief detach current output stream and restore to previous stream
+ void detach() throw(DebugStreamError) {
+ if (current->next == 0)
+ DUNE_THROW(DebugStreamError, "Cannot detach initial stream!");
+ if (_tied)
+ DUNE_THROW(DebugStreamError, "Cannot detach a tied stream!");
+
+ StreamWrap* old = current;
+ current = current->next;
+ delete old;
+ };
+
+ // \brief Tie a stream to this one.
+ void tie(DebugStreamState& to) throw(DebugStreamError) {
+ if (to._tied)
+ DUNE_THROW(DebugStreamError, "Cannot tie to an already tied stream!");
+ if (_tied)
+ DUNE_THROW(DebugStreamError, "Stream already tied: untie first!");
+
+ _tied = true;
+ tiedstate = &to;
+
+ // tell master class
+ tiedstate->_tied_streams++;
+ };
+
+ //! \brief Untie stream
+ void untie() throw(DebugStreamError) {
+ if(! _tied)
+ DUNE_THROW(DebugStreamError, "Cannot untie, stream is not tied!");
+
+ tiedstate->_tied_streams--;
+ _tied = false;
+ tiedstate = 0;
+ };
+
+ private:
+ //! \brief pointer to data of stream we're tied to
+ DebugStreamState* tiedstate;
+
+ /*! \brief Activation state history.
+
+ store old activation settings so that the outside code doesn't
+ need to remember */
+ std::stack<bool> _actstack;
+ };
+
+ /** /} */
+}
+
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id: fmatrix.hh 6128 2010-09-08 13:50:00Z christi $
+#ifndef DUNE_DENSEMATRIX_HH
+#define DUNE_DENSEMATRIX_HH
+
+#include <cmath>
+#include <cstddef>
+#include <iostream>
+#include <vector>
+
+#include <dune/common/exceptions.hh>
+#include <dune/common/fvector.hh>
+#include <dune/common/precision.hh>
+#include <dune/common/static_assert.hh>
+#include <dune/common/classname.hh>
+#include <dune/common/math.hh>
+#include <dune/common/unused.hh>
+
+
+namespace Dune
+{
+
+ template<typename M> class DenseMatrix;
+
+ template<typename M>
+ struct FieldTraits< DenseMatrix<M> >
+ {
+ typedef const typename FieldTraits< typename DenseMatVecTraits<M>::value_type >::field_type field_type;
+ typedef const typename FieldTraits< typename DenseMatVecTraits<M>::value_type >::real_type real_type;
+ };
+
+ /*
+ work around a problem of FieldMatrix/FieldVector,
+ there is no unique way to obtain the size of a class
+ */
+ template<class K, int N, int M> class FieldMatrix;
+ template<class K, int N> class FieldVector;
+ namespace {
+ template<class V>
+ struct VectorSize
+ {
+ static typename V::size_type size(const V & v) { return v.size(); }
+ };
+
+ template<class K, int N>
+ struct VectorSize< const FieldVector<K,N> >
+ {
+ typedef FieldVector<K,N> V;
+ static typename V::size_type size(const V & v) { return N; }
+ };
+ }
+
+ /**
+ @addtogroup DenseMatVec
+ @{
+ */
+
+ /*! \file
+
+ \brief Implements a matrix constructed from a given type
+ representing a field and a compile-time given number of rows and columns.
+ */
+
+
+
+ /**
+ \brief you have to specialize this structure for any type that should be assignable to a DenseMatrix
+ \tparam DenseMatrix Some type implementing the dense matrix interface
+ \tparam RHS Right hand side type
+ */
+ template< class DenseMatrix, class RHS >
+ struct DenseMatrixAssigner;
+
+
+
+ template< class DenseMatrix, class K, int N, int M >
+ void istl_assign_to_fmatrix ( DenseMatrix &denseMatrix, const K (&values)[ M ][ N ] )
+ {
+ for( int i = 0; i < N; ++i )
+ for( int j = 0; j < M; ++j )
+ denseMatrix[ i ][ j ] = values[ i ][ j ];
+ }
+
+
+
+#ifndef DOXYGEN
+ namespace
+ {
+ template< class DenseMatrix, class RHS,
+ bool primitive = Conversion< RHS, typename DenseMatrix::field_type >::exists >
+ class DenseMatrixAssignerImplementation;
+
+ template< class DenseMatrix, class RHS >
+ class DenseMatrixAssignerImplementation< DenseMatrix, RHS, true >
+ {
+ public:
+ static void apply ( DenseMatrix &denseMatrix, const RHS &rhs )
+ {
+ typedef typename DenseMatrix::field_type field_type;
+
+ const field_type value = static_cast< field_type >( rhs );
+
+ const std::size_t size = denseMatrix.size();
+ for( std::size_t i = 0; i < size; ++i )
+ denseMatrix[ i ] = value;
+ }
+ };
+
+ template< class DenseMatrix, class RHS >
+ class DenseMatrixAssignerImplementation< DenseMatrix, RHS, false >
+ {
+ template< class M, class T>
+ struct have_istl_assign_to_fmatrix
+ {
+ struct yes { char dummy[ 1 ]; };
+ struct no { char dummy[ 2 ]; };
+
+ template< class C>
+ static C &get_ref();
+
+ template< class C>
+ static yes test( decltype( istl_assign_to_fmatrix( get_ref< M >(), get_ref< C >() ) ) * );
+ template< class C >
+ static no test(...);
+
+ public:
+ static const bool v = sizeof( test< const T >( 0 ) ) == sizeof( yes );
+ };
+
+ template< class M, class T, bool = have_istl_assign_to_fmatrix< M, T >::v >
+ struct DefaultImplementation;
+
+ // forward to istl_assign_to_fmatrix()
+ template< class M, class T >
+ struct DefaultImplementation< M, T, true >
+ {
+ static void apply ( M &m, const T &t )
+ {
+ istl_assign_to_fmatrix( m, t );
+ }
+ };
+
+ // static_cast
+ template< class M, class T >
+ struct DefaultImplementation< M, T, false >
+ {
+ static void apply ( M &m, const T &t )
+ {
+ dune_static_assert( (Conversion< const T, const M >::exists), "No template specialization of DenseMatrixAssigner found" );
+ m = static_cast< const M & >( t );
+ }
+ };
+
+ public:
+ static void apply ( DenseMatrix &denseMatrix, const RHS &rhs )
+ {
+ DefaultImplementation< DenseMatrix, RHS >::apply( denseMatrix, rhs );
+ }
+ };
+ }
+
+
+
+ template< class DenseMatrix, class RHS >
+ struct DenseMatrixAssigner
+ {
+ static void apply ( DenseMatrix &denseMatrix, const RHS &rhs )
+ {
+ DenseMatrixAssignerImplementation< DenseMatrix, RHS >::apply( denseMatrix, rhs );
+ }
+ };
+#endif // #ifndef DOXYGEN
+
+
+
+ /** @brief Error thrown if operations of a FieldMatrix fail. */
+ class FMatrixError : public Exception {};
+
+ /**
+ @brief A dense n x m matrix.
+
+ Matrices represent linear maps from a vector space V to a vector space W.
+ This class represents such a linear map by storing a two-dimensional
+ %array of numbers of a given field type K. The number of rows and
+ columns is given at compile time.
+
+ \tparam MAT type of the matrix implementation
+ */
+ template<typename MAT>
+ class DenseMatrix
+ {
+ typedef DenseMatVecTraits<MAT> Traits;
+
+ // Curiously recurring template pattern
+ MAT & asImp() { return static_cast<MAT&>(*this); }
+ const MAT & asImp() const { return static_cast<const MAT&>(*this); }
+
+ public:
+ //===== type definitions and constants
+
+ //! type of derived matrix class
+ typedef typename Traits::derived_type derived_type;
+
+ //! export the type representing the field
+ typedef typename Traits::value_type value_type;
+
+ //! export the type representing the field
+ typedef typename Traits::value_type field_type;
+
+ //! export the type representing the components
+ typedef typename Traits::value_type block_type;
+
+ //! The type used for the index access and size operation
+ typedef typename Traits::size_type size_type;
+
+ //! The type used to represent a row (must fulfill the Dune::DenseVector interface)
+ typedef typename Traits::row_type row_type;
+
+ //! The type used to represent a reference to a row (usually row_type &)
+ typedef typename Traits::row_reference row_reference;
+
+ //! The type used to represent a reference to a constant row (usually const row_type &)
+ typedef typename Traits::const_row_reference const_row_reference;
+
+ //! We are at the leaf of the block recursion
+ enum {
+ //! The number of block levels we contain. This is 1.
+ blocklevel = 1
+ };
+
+ //===== access to components
+
+ //! random access
+ row_reference operator[] ( size_type i )
+ {
+ return asImp().mat_access(i);
+ }
+
+ const_row_reference operator[] ( size_type i ) const
+ {
+ return asImp().mat_access(i);
+ }
+
+ //! size method (number of rows)
+ size_type size() const
+ {
+ return rows();
+ }
+
+ //===== iterator interface to rows of the matrix
+ //! Iterator class for sequential access
+ typedef DenseIterator<DenseMatrix,row_type> Iterator;
+ //! typedef for stl compliant access
+ typedef Iterator iterator;
+ //! rename the iterators for easier access
+ typedef Iterator RowIterator;
+ //! rename the iterators for easier access
+ typedef typename row_type::Iterator ColIterator;
+
+ //! begin iterator
+ Iterator begin ()
+ {
+ return Iterator(*this,0);
+ }
+
+ //! end iterator
+ Iterator end ()
+ {
+ return Iterator(*this,rows());
+ }
+
+ //! @returns an iterator that is positioned before
+ //! the end iterator of the vector, i.e. at the last entry.
+ Iterator beforeEnd ()
+ {
+ return Iterator(*this,rows()-1);
+ }
+
+ //! @returns an iterator that is positioned before
+ //! the first entry of the vector.
+ Iterator beforeBegin ()
+ {
+ return Iterator(*this,-1);
+ }
+
+ //! Iterator class for sequential access
+ typedef DenseIterator<const DenseMatrix,const row_type> ConstIterator;
+ //! typedef for stl compliant access
+ typedef ConstIterator const_iterator;
+ //! rename the iterators for easier access
+ typedef ConstIterator ConstRowIterator;
+ //! rename the iterators for easier access
+ typedef typename row_type::ConstIterator ConstColIterator;
+
+ //! begin iterator
+ ConstIterator begin () const
+ {
+ return ConstIterator(*this,0);
+ }
+
+ //! end iterator
+ ConstIterator end () const
+ {
+ return ConstIterator(*this,rows());
+ }
+
+ //! @returns an iterator that is positioned before
+ //! the end iterator of the vector. i.e. at the last element
+ ConstIterator beforeEnd () const
+ {
+ return ConstIterator(*this,rows()-1);
+ }
+
+ //! @returns an iterator that is positioned before
+ //! the first entry of the vector.
+ ConstIterator beforeBegin () const
+ {
+ return ConstIterator(*this,-1);
+ }
+
+ //===== assignment
+
+ template< class RHS >
+ DenseMatrix &operator= ( const RHS &rhs )
+ {
+ DenseMatrixAssigner< MAT, RHS >::apply( asImp(), rhs );
+ return *this;
+ }
+
+ //===== vector space arithmetic
+
+ //! vector space addition
+ template <class Other>
+ DenseMatrix& operator+= (const DenseMatrix<Other>& y)
+ {
+ for (size_type i=0; i<rows(); i++)
+ (*this)[i] += y[i];
+ return *this;
+ }
+
+ //! vector space subtraction
+ template <class Other>
+ DenseMatrix& operator-= (const DenseMatrix<Other>& y)
+ {
+ for (size_type i=0; i<rows(); i++)
+ (*this)[i] -= y[i];
+ return *this;
+ }
+
+ //! vector space multiplication with scalar
+ DenseMatrix& operator*= (const field_type& k)
+ {
+ for (size_type i=0; i<rows(); i++)
+ (*this)[i] *= k;
+ return *this;
+ }
+
+ //! vector space division by scalar
+ DenseMatrix& operator/= (const field_type& k)
+ {
+ for (size_type i=0; i<rows(); i++)
+ (*this)[i] /= k;
+ return *this;
+ }
+
+ //! vector space axpy operation (*this += k y)
+ template <class Other>
+ DenseMatrix &axpy (const field_type &k, const DenseMatrix<Other> &y )
+ {
+ for( size_type i = 0; i < rows(); ++i )
+ (*this)[ i ].axpy( k, y[ i ] );
+ return *this;
+ }
+
+ //! Binary matrix comparison
+ template <class Other>
+ bool operator== (const DenseMatrix<Other>& y) const
+ {
+ for (size_type i=0; i<rows(); i++)
+ if ((*this)[i]!=y[i])
+ return false;
+ return true;
+ }
+ //! Binary matrix incomparison
+ template <class Other>
+ bool operator!= (const DenseMatrix<Other>& y) const
+ {
+ return !operator==(y);
+ }
+
+
+ //===== linear maps
+
+ //! y = A x
+ template<class X, class Y>
+ void mv (const X& x, Y& y) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (x.N()!=M()) DUNE_THROW(FMatrixError,"Index out of range");
+ if (y.N()!=N()) DUNE_THROW(FMatrixError,"Index out of range");
+#endif
+ for (size_type i=0; i<rows(); ++i)
+ {
+ y[i] = 0;
+ for (size_type j=0; j<cols(); j++)
+ y[i] += (*this)[i][j] * x[j];
+ }
+ }
+
+ //! y = A^T x
+ template< class X, class Y >
+ void mtv ( const X &x, Y &y ) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ //assert( &x != &y );
+ //This assert did not work for me. Compile error:
+ // comparison between distinct pointer types ‘const
+ // Dune::FieldVector<double, 3>*’ and ‘Dune::FieldVector<double, 2>*’ lacks a cast
+ if( x.N() != N() )
+ DUNE_THROW( FMatrixError, "Index out of range." );
+ if( y.N() != M() )
+ DUNE_THROW( FMatrixError, "Index out of range." );
+#endif
+ for( size_type i = 0; i < cols(); ++i )
+ {
+ y[ i ] = 0;
+ for( size_type j = 0; j < rows(); ++j )
+ y[ i ] += (*this)[ j ][ i ] * x[ j ];
+ }
+ }
+
+ //! y += A x
+ template<class X, class Y>
+ void umv (const X& x, Y& y) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (x.N()!=M())
+ DUNE_THROW(FMatrixError,"y += A x -- index out of range (sizes: x: " << x.N() << ", y: " << y.N() << ", A: " << this->N() << " x " << this->M() << ")" << std::endl);
+ if (y.N()!=N())
+ DUNE_THROW(FMatrixError,"y += A x -- index out of range (sizes: x: " << x.N() << ", y: " << y.N() << ", A: " << this->N() << " x " << this->M() << ")" << std::endl);
+#endif
+ for (size_type i=0; i<rows(); i++)
+ for (size_type j=0; j<cols(); j++)
+ y[i] += (*this)[i][j] * x[j];
+ }
+
+ //! y += A^T x
+ template<class X, class Y>
+ void umtv (const X& x, Y& y) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
+ if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
+#endif
+
+ for (size_type i=0; i<rows(); i++)
+ for (size_type j=0; j<cols(); j++)
+ y[j] += (*this)[i][j]*x[i];
+ }
+
+ //! y += A^H x
+ template<class X, class Y>
+ void umhv (const X& x, Y& y) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
+ if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
+#endif
+
+ for (size_type i=0; i<rows(); i++)
+ for (size_type j=0; j<cols(); j++)
+ y[j] += conjugateComplex((*this)[i][j])*x[i];
+ }
+
+ //! y -= A x
+ template<class X, class Y>
+ void mmv (const X& x, Y& y) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
+ if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
+#endif
+ for (size_type i=0; i<rows(); i++)
+ for (size_type j=0; j<cols(); j++)
+ y[i] -= (*this)[i][j] * x[j];
+ }
+
+ //! y -= A^T x
+ template<class X, class Y>
+ void mmtv (const X& x, Y& y) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
+ if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
+#endif
+
+ for (size_type i=0; i<rows(); i++)
+ for (size_type j=0; j<cols(); j++)
+ y[j] -= (*this)[i][j]*x[i];
+ }
+
+ //! y -= A^H x
+ template<class X, class Y>
+ void mmhv (const X& x, Y& y) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
+ if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
+#endif
+
+ for (size_type i=0; i<rows(); i++)
+ for (size_type j=0; j<cols(); j++)
+ y[j] -= conjugateComplex((*this)[i][j])*x[i];
+ }
+
+ //! y += alpha A x
+ template<class X, class Y>
+ void usmv (const field_type& alpha, const X& x, Y& y) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
+ if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
+#endif
+ for (size_type i=0; i<rows(); i++)
+ for (size_type j=0; j<cols(); j++)
+ y[i] += alpha * (*this)[i][j] * x[j];
+ }
+
+ //! y += alpha A^T x
+ template<class X, class Y>
+ void usmtv (const field_type& alpha, const X& x, Y& y) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
+ if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
+#endif
+
+ for (size_type i=0; i<rows(); i++)
+ for (size_type j=0; j<cols(); j++)
+ y[j] += alpha*(*this)[i][j]*x[i];
+ }
+
+ //! y += alpha A^H x
+ template<class X, class Y>
+ void usmhv (const field_type& alpha, const X& x, Y& y) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
+ if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
+#endif
+
+ for (size_type i=0; i<rows(); i++)
+ for (size_type j=0; j<cols(); j++)
+ y[j] += alpha*conjugateComplex((*this)[i][j])*x[i];
+ }
+
+ //===== norms
+
+ //! frobenius norm: sqrt(sum over squared values of entries)
+ typename FieldTraits<value_type>::real_type frobenius_norm () const
+ {
+ typename FieldTraits<value_type>::real_type sum=(0.0);
+ for (size_type i=0; i<rows(); ++i) sum += (*this)[i].two_norm2();
+ return fvmeta::sqrt(sum);
+ }
+
+ //! square of frobenius norm, need for block recursion
+ typename FieldTraits<value_type>::real_type frobenius_norm2 () const
+ {
+ typename FieldTraits<value_type>::real_type sum=(0.0);
+ for (size_type i=0; i<rows(); ++i) sum += (*this)[i].two_norm2();
+ return sum;
+ }
+
+ //! infinity norm (row sum norm, how to generalize for blocks?)
+ typename FieldTraits<value_type>::real_type infinity_norm () const
+ {
+ if (size() == 0)
+ return 0.0;
+
+ ConstIterator it = begin();
+ typename remove_const< typename FieldTraits<value_type>::real_type >::type max = it->one_norm();
+ for (it = it + 1; it != end(); ++it)
+ max = std::max(max, it->one_norm());
+
+ return max;
+ }
+
+ //! simplified infinity norm (uses Manhattan norm for complex values)
+ typename FieldTraits<value_type>::real_type infinity_norm_real () const
+ {
+ if (size() == 0)
+ return 0.0;
+
+ ConstIterator it = begin();
+ typename remove_const< typename FieldTraits<value_type>::real_type >::type max = it->one_norm_real();
+ for (it = it + 1; it != end(); ++it)
+ max = std::max(max, it->one_norm_real());
+
+ return max;
+ }
+
+ //===== solve
+
+ /** \brief Solve system A x = b
+ *
+ * \exception FMatrixError if the matrix is singular
+ */
+ template <class V>
+ void solve (V& x, const V& b) const;
+
+ /** \brief Compute inverse
+ *
+ * \exception FMatrixError if the matrix is singular
+ */
+ void invert();
+
+ //! calculates the determinant of this matrix
+ field_type determinant () const;
+
+ //! Multiplies M from the left to this matrix
+ template<typename M2>
+ MAT& leftmultiply (const DenseMatrix<M2>& M)
+ {
+ assert(M.rows() == M.cols() && M.rows() == rows());
+ MAT C(asImp());
+
+ for (size_type i=0; i<rows(); i++)
+ for (size_type j=0; j<cols(); j++) {
+ (*this)[i][j] = 0;
+ for (size_type k=0; k<rows(); k++)
+ (*this)[i][j] += M[i][k]*C[k][j];
+ }
+
+ return asImp();
+ }
+
+ //! Multiplies M from the right to this matrix
+ template<typename M2>
+ MAT& rightmultiply (const DenseMatrix<M2>& M)
+ {
+ assert(M.rows() == M.cols() && M.cols() == cols());
+ MAT C(asImp());
+
+ for (size_type i=0; i<rows(); i++)
+ for (size_type j=0; j<cols(); j++) {
+ (*this)[i][j] = 0;
+ for (size_type k=0; k<cols(); k++)
+ (*this)[i][j] += C[i][k]*M[k][j];
+ }
+ return asImp();
+ }
+
+#if 0
+ //! Multiplies M from the left to this matrix, this matrix is not modified
+ template<int l>
+ DenseMatrix<K,l,cols> leftmultiplyany (const FieldMatrix<K,l,rows>& M) const
+ {
+ FieldMatrix<K,l,cols> C;
+
+ for (size_type i=0; i<l; i++) {
+ for (size_type j=0; j<cols(); j++) {
+ C[i][j] = 0;
+ for (size_type k=0; k<rows(); k++)
+ C[i][j] += M[i][k]*(*this)[k][j];
+ }
+ }
+ return C;
+ }
+
+ //! Multiplies M from the right to this matrix, this matrix is not modified
+ template<int l>
+ FieldMatrix<K,rows,l> rightmultiplyany (const FieldMatrix<K,cols,l>& M) const
+ {
+ FieldMatrix<K,rows,l> C;
+
+ for (size_type i=0; i<rows(); i++) {
+ for (size_type j=0; j<l; j++) {
+ C[i][j] = 0;
+ for (size_type k=0; k<cols(); k++)
+ C[i][j] += (*this)[i][k]*M[k][j];
+ }
+ }
+ return C;
+ }
+#endif
+
+ //===== sizes
+
+ //! number of rows
+ size_type N () const
+ {
+ return rows();
+ }
+
+ //! number of columns
+ size_type M () const
+ {
+ return cols();
+ }
+
+ //! number of rows
+ size_type rows() const
+ {
+ return asImp().mat_rows();
+ }
+
+ //! number of columns
+ size_type cols() const
+ {
+ return asImp().mat_cols();
+ }
+
+ //===== query
+
+ //! return true when (i,j) is in pattern
+ bool exists (size_type i, size_type j) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (i<0 || i>=rows()) DUNE_THROW(FMatrixError,"row index out of range");
+ if (j<0 || j>=cols()) DUNE_THROW(FMatrixError,"column index out of range");
+#else
+ DUNE_UNUSED_PARAMETER(i);
+ DUNE_UNUSED_PARAMETER(j);
+#endif
+ return true;
+ }
+
+ private:
+
+#ifndef DOXYGEN
+ struct ElimPivot
+ {
+ ElimPivot(std::vector<size_type> & pivot);
+
+ void swap(int i, int j);
+
+ template<typename T>
+ void operator()(const T&, int, int)
+ {}
+
+ std::vector<size_type> & pivot_;
+ };
+
+ template<typename V>
+ struct Elim
+ {
+ Elim(V& rhs);
+
+ void swap(int i, int j);
+
+ void operator()(const typename V::field_type& factor, int k, int i);
+
+ V* rhs_;
+ };
+
+ struct ElimDet
+ {
+ ElimDet(field_type& sign) : sign_(sign)
+ { sign_ = 1; }
+
+ void swap(int, int)
+ { sign_ *= -1; }
+
+ void operator()(const field_type&, int, int)
+ {}
+
+ field_type& sign_;
+ };
+#endif // DOXYGEN
+
+ template<class Func>
+ void luDecomposition(DenseMatrix<MAT>& A, Func func) const;
+ };
+
+#ifndef DOXYGEN
+ template<typename MAT>
+ DenseMatrix<MAT>::ElimPivot::ElimPivot(std::vector<size_type> & pivot)
+ : pivot_(pivot)
+ {
+ typedef typename std::vector<size_type>::size_type size_type;
+ for(size_type i=0; i < pivot_.size(); ++i) pivot_[i]=i;
+ }
+
+ template<typename MAT>
+ void DenseMatrix<MAT>::ElimPivot::swap(int i, int j)
+ {
+ pivot_[i]=j;
+ }
+
+ template<typename MAT>
+ template<typename V>
+ DenseMatrix<MAT>::Elim<V>::Elim(V& rhs)
+ : rhs_(&rhs)
+ {}
+
+ template<typename MAT>
+ template<typename V>
+ void DenseMatrix<MAT>::Elim<V>::swap(int i, int j)
+ {
+ std::swap((*rhs_)[i], (*rhs_)[j]);
+ }
+
+ template<typename MAT>
+ template<typename V>
+ void DenseMatrix<MAT>::
+ Elim<V>::operator()(const typename V::field_type& factor, int k, int i)
+ {
+ (*rhs_)[k] -= factor*(*rhs_)[i];
+ }
+ template<typename MAT>
+ template<typename Func>
+ inline void DenseMatrix<MAT>::luDecomposition(DenseMatrix<MAT>& A, Func func) const
+ {
+ typedef typename FieldTraits<value_type>::real_type
+ real_type;
+ real_type norm = A.infinity_norm_real(); // for relative thresholds
+ real_type pivthres = std::max( FMatrixPrecision< real_type >::absolute_limit(), norm * FMatrixPrecision< real_type >::pivoting_limit() );
+ real_type singthres = std::max( FMatrixPrecision< real_type >::absolute_limit(), norm * FMatrixPrecision< real_type >::singular_limit() );
+
+ // LU decomposition of A in A
+ for (size_type i=0; i<rows(); i++) // loop over all rows
+ {
+ typename FieldTraits<value_type>::real_type pivmax=fvmeta::absreal(A[i][i]);
+
+ // pivoting ?
+ if (pivmax<pivthres)
+ {
+ // compute maximum of column
+ size_type imax=i;
+ typename FieldTraits<value_type>::real_type abs(0.0);
+ for (size_type k=i+1; k<rows(); k++)
+ if ((abs=fvmeta::absreal(A[k][i]))>pivmax)
+ {
+ pivmax = abs; imax = k;
+ }
+ // swap rows
+ if (imax!=i) {
+ for (size_type j=0; j<rows(); j++)
+ std::swap(A[i][j],A[imax][j]);
+ func.swap(i, imax); // swap the pivot or rhs
+ }
+ }
+
+ // singular ?
+ if (pivmax<singthres)
+ DUNE_THROW(FMatrixError,"matrix is singular");
+
+ // eliminate
+ for (size_type k=i+1; k<rows(); k++)
+ {
+ field_type factor = A[k][i]/A[i][i];
+ A[k][i] = factor;
+ for (size_type j=i+1; j<rows(); j++)
+ A[k][j] -= factor*A[i][j];
+ func(factor, k, i);
+ }
+ }
+ }
+
+ template<typename MAT>
+ template <class V>
+ inline void DenseMatrix<MAT>::solve(V& x, const V& b) const
+ {
+ // never mind those ifs, because they get optimized away
+ if (rows()!=cols())
+ DUNE_THROW(FMatrixError, "Can't solve for a " << rows() << "x" << cols() << " matrix!");
+
+ if (rows()==1) {
+
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (fvmeta::absreal((*this)[0][0])<FMatrixPrecision<>::absolute_limit())
+ DUNE_THROW(FMatrixError,"matrix is singular");
+#endif
+ x[0] = b[0]/(*this)[0][0];
+
+ }
+ else if (rows()==2) {
+
+ field_type detinv = (*this)[0][0]*(*this)[1][1]-(*this)[0][1]*(*this)[1][0];
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (fvmeta::absreal(detinv)<FMatrixPrecision<>::absolute_limit())
+ DUNE_THROW(FMatrixError,"matrix is singular");
+#endif
+ detinv = 1.0/detinv;
+
+ x[0] = detinv*((*this)[1][1]*b[0]-(*this)[0][1]*b[1]);
+ x[1] = detinv*((*this)[0][0]*b[1]-(*this)[1][0]*b[0]);
+
+ }
+ else if (rows()==3) {
+
+ field_type d = determinant();
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (fvmeta::absreal(d)<FMatrixPrecision<>::absolute_limit())
+ DUNE_THROW(FMatrixError,"matrix is singular");
+#endif
+
+ x[0] = (b[0]*(*this)[1][1]*(*this)[2][2] - b[0]*(*this)[2][1]*(*this)[1][2]
+ - b[1] *(*this)[0][1]*(*this)[2][2] + b[1]*(*this)[2][1]*(*this)[0][2]
+ + b[2] *(*this)[0][1]*(*this)[1][2] - b[2]*(*this)[1][1]*(*this)[0][2]) / d;
+
+ x[1] = ((*this)[0][0]*b[1]*(*this)[2][2] - (*this)[0][0]*b[2]*(*this)[1][2]
+ - (*this)[1][0] *b[0]*(*this)[2][2] + (*this)[1][0]*b[2]*(*this)[0][2]
+ + (*this)[2][0] *b[0]*(*this)[1][2] - (*this)[2][0]*b[1]*(*this)[0][2]) / d;
+
+ x[2] = ((*this)[0][0]*(*this)[1][1]*b[2] - (*this)[0][0]*(*this)[2][1]*b[1]
+ - (*this)[1][0] *(*this)[0][1]*b[2] + (*this)[1][0]*(*this)[2][1]*b[0]
+ + (*this)[2][0] *(*this)[0][1]*b[1] - (*this)[2][0]*(*this)[1][1]*b[0]) / d;
+
+ }
+ else {
+
+ V& rhs = x; // use x to store rhs
+ rhs = b; // copy data
+ Elim<V> elim(rhs);
+ MAT A(asImp());
+
+ luDecomposition(A, elim);
+
+ // backsolve
+ for(int i=rows()-1; i>=0; i--) {
+ for (size_type j=i+1; j<rows(); j++)
+ rhs[i] -= A[i][j]*x[j];
+ x[i] = rhs[i]/A[i][i];
+ }
+ }
+ }
+
+ template<typename MAT>
+ inline void DenseMatrix<MAT>::invert()
+ {
+ // never mind those ifs, because they get optimized away
+ if (rows()!=cols())
+ DUNE_THROW(FMatrixError, "Can't invert a " << rows() << "x" << cols() << " matrix!");
+
+ if (rows()==1) {
+
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (fvmeta::absreal((*this)[0][0])<FMatrixPrecision<>::absolute_limit())
+ DUNE_THROW(FMatrixError,"matrix is singular");
+#endif
+ (*this)[0][0] = field_type( 1 ) / (*this)[0][0];
+
+ }
+ else if (rows()==2) {
+
+ field_type detinv = (*this)[0][0]*(*this)[1][1]-(*this)[0][1]*(*this)[1][0];
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (fvmeta::absreal(detinv)<FMatrixPrecision<>::absolute_limit())
+ DUNE_THROW(FMatrixError,"matrix is singular");
+#endif
+ detinv = field_type( 1 ) / detinv;
+
+ field_type temp=(*this)[0][0];
+ (*this)[0][0] = (*this)[1][1]*detinv;
+ (*this)[0][1] = -(*this)[0][1]*detinv;
+ (*this)[1][0] = -(*this)[1][0]*detinv;
+ (*this)[1][1] = temp*detinv;
+
+ }
+ else {
+
+ MAT A(asImp());
+ std::vector<size_type> pivot(rows());
+ luDecomposition(A, ElimPivot(pivot));
+ DenseMatrix<MAT>& L=A;
+ DenseMatrix<MAT>& U=A;
+
+ // initialize inverse
+ *this=field_type();
+
+ for(size_type i=0; i<rows(); ++i)
+ (*this)[i][i]=1;
+
+ // L Y = I; multiple right hand sides
+ for (size_type i=0; i<rows(); i++)
+ for (size_type j=0; j<i; j++)
+ for (size_type k=0; k<rows(); k++)
+ (*this)[i][k] -= L[i][j]*(*this)[j][k];
+
+ // U A^{-1} = Y
+ for (size_type i=rows(); i>0;) {
+ --i;
+ for (size_type k=0; k<rows(); k++) {
+ for (size_type j=i+1; j<rows(); j++)
+ (*this)[i][k] -= U[i][j]*(*this)[j][k];
+ (*this)[i][k] /= U[i][i];
+ }
+ }
+
+ for(size_type i=rows(); i>0; ) {
+ --i;
+ if(i!=pivot[i])
+ for(size_type j=0; j<rows(); ++j)
+ std::swap((*this)[j][pivot[i]], (*this)[j][i]);
+ }
+ }
+ }
+
+ // implementation of the determinant
+ template<typename MAT>
+ inline typename DenseMatrix<MAT>::field_type
+ DenseMatrix<MAT>::determinant() const
+ {
+ // never mind those ifs, because they get optimized away
+ if (rows()!=cols())
+ DUNE_THROW(FMatrixError, "There is no determinant for a " << rows() << "x" << cols() << " matrix!");
+
+ if (rows()==1)
+ return (*this)[0][0];
+
+ if (rows()==2)
+ return (*this)[0][0]*(*this)[1][1] - (*this)[0][1]*(*this)[1][0];
+
+ if (rows()==3) {
+ // code generated by maple
+ field_type t4 = (*this)[0][0] * (*this)[1][1];
+ field_type t6 = (*this)[0][0] * (*this)[1][2];
+ field_type t8 = (*this)[0][1] * (*this)[1][0];
+ field_type t10 = (*this)[0][2] * (*this)[1][0];
+ field_type t12 = (*this)[0][1] * (*this)[2][0];
+ field_type t14 = (*this)[0][2] * (*this)[2][0];
+
+ return (t4*(*this)[2][2]-t6*(*this)[2][1]-t8*(*this)[2][2]+
+ t10*(*this)[2][1]+t12*(*this)[1][2]-t14*(*this)[1][1]);
+
+ }
+
+ MAT A(asImp());
+ field_type det;
+ try
+ {
+ luDecomposition(A, ElimDet(det));
+ }
+ catch (FMatrixError&)
+ {
+ return 0;
+ }
+ for (size_type i = 0; i < rows(); ++i)
+ det *= A[i][i];
+ return det;
+ }
+
+#endif // DOXYGEN
+
+ namespace DenseMatrixHelp {
+#if 0
+ //! invert scalar without changing the original matrix
+ template <typename K>
+ static inline K invertMatrix (const FieldMatrix<K,1,1> &matrix, FieldMatrix<K,1,1> &inverse)
+ {
+ inverse[0][0] = 1.0/matrix[0][0];
+ return matrix[0][0];
+ }
+
+ //! invert scalar without changing the original matrix
+ template <typename K>
+ static inline K invertMatrix_retTransposed (const FieldMatrix<K,1,1> &matrix, FieldMatrix<K,1,1> &inverse)
+ {
+ return invertMatrix(matrix,inverse);
+ }
+
+
+ //! invert 2x2 Matrix without changing the original matrix
+ template <typename K>
+ static inline K invertMatrix (const FieldMatrix<K,2,2> &matrix, FieldMatrix<K,2,2> &inverse)
+ {
+ // code generated by maple
+ field_type det = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
+ field_type det_1 = 1.0/det;
+ inverse[0][0] = matrix[1][1] * det_1;
+ inverse[0][1] = - matrix[0][1] * det_1;
+ inverse[1][0] = - matrix[1][0] * det_1;
+ inverse[1][1] = matrix[0][0] * det_1;
+ return det;
+ }
+
+ //! invert 2x2 Matrix without changing the original matrix
+ //! return transposed matrix
+ template <typename K>
+ static inline K invertMatrix_retTransposed (const FieldMatrix<K,2,2> &matrix, FieldMatrix<K,2,2> &inverse)
+ {
+ // code generated by maple
+ field_type det = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
+ field_type det_1 = 1.0/det;
+ inverse[0][0] = matrix[1][1] * det_1;
+ inverse[1][0] = - matrix[0][1] * det_1;
+ inverse[0][1] = - matrix[1][0] * det_1;
+ inverse[1][1] = matrix[0][0] * det_1;
+ return det;
+ }
+
+ //! invert 3x3 Matrix without changing the original matrix
+ template <typename K>
+ static inline K invertMatrix (const FieldMatrix<K,3,3> &matrix, FieldMatrix<K,3,3> &inverse)
+ {
+ // code generated by maple
+ field_type t4 = matrix[0][0] * matrix[1][1];
+ field_type t6 = matrix[0][0] * matrix[1][2];
+ field_type t8 = matrix[0][1] * matrix[1][0];
+ field_type t10 = matrix[0][2] * matrix[1][0];
+ field_type t12 = matrix[0][1] * matrix[2][0];
+ field_type t14 = matrix[0][2] * matrix[2][0];
+
+ field_type det = (t4*matrix[2][2]-t6*matrix[2][1]-t8*matrix[2][2]+
+ t10*matrix[2][1]+t12*matrix[1][2]-t14*matrix[1][1]);
+ field_type t17 = 1.0/det;
+
+ inverse[0][0] = (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1])*t17;
+ inverse[0][1] = -(matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1])*t17;
+ inverse[0][2] = (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])*t17;
+ inverse[1][0] = -(matrix[1][0] * matrix[2][2] - matrix[1][2] * matrix[2][0])*t17;
+ inverse[1][1] = (matrix[0][0] * matrix[2][2] - t14) * t17;
+ inverse[1][2] = -(t6-t10) * t17;
+ inverse[2][0] = (matrix[1][0] * matrix[2][1] - matrix[1][1] * matrix[2][0]) * t17;
+ inverse[2][1] = -(matrix[0][0] * matrix[2][1] - t12) * t17;
+ inverse[2][2] = (t4-t8) * t17;
+
+ return det;
+ }
+
+ //! invert 3x3 Matrix without changing the original matrix
+ template <typename K>
+ static inline K invertMatrix_retTransposed (const FieldMatrix<K,3,3> &matrix, FieldMatrix<K,3,3> &inverse)
+ {
+ // code generated by maple
+ field_type t4 = matrix[0][0] * matrix[1][1];
+ field_type t6 = matrix[0][0] * matrix[1][2];
+ field_type t8 = matrix[0][1] * matrix[1][0];
+ field_type t10 = matrix[0][2] * matrix[1][0];
+ field_type t12 = matrix[0][1] * matrix[2][0];
+ field_type t14 = matrix[0][2] * matrix[2][0];
+
+ field_type det = (t4*matrix[2][2]-t6*matrix[2][1]-t8*matrix[2][2]+
+ t10*matrix[2][1]+t12*matrix[1][2]-t14*matrix[1][1]);
+ field_type t17 = 1.0/det;
+
+ inverse[0][0] = (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1])*t17;
+ inverse[1][0] = -(matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1])*t17;
+ inverse[2][0] = (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])*t17;
+ inverse[0][1] = -(matrix[1][0] * matrix[2][2] - matrix[1][2] * matrix[2][0])*t17;
+ inverse[1][1] = (matrix[0][0] * matrix[2][2] - t14) * t17;
+ inverse[2][1] = -(t6-t10) * t17;
+ inverse[0][2] = (matrix[1][0] * matrix[2][1] - matrix[1][1] * matrix[2][0]) * t17;
+ inverse[1][2] = -(matrix[0][0] * matrix[2][1] - t12) * t17;
+ inverse[2][2] = (t4-t8) * t17;
+
+ return det;
+ }
+
+ //! calculates ret = A * B
+ template< class K, int m, int n, int p >
+ static inline void multMatrix ( const FieldMatrix< K, m, n > &A,
+ const FieldMatrix< K, n, p > &B,
+ FieldMatrix< K, m, p > &ret )
+ {
+ typedef typename FieldMatrix< K, m, p > :: size_type size_type;
+
+ for( size_type i = 0; i < m; ++i )
+ {
+ for( size_type j = 0; j < p; ++j )
+ {
+ ret[ i ][ j ] = K( 0 );
+ for( size_type k = 0; k < n; ++k )
+ ret[ i ][ j ] += A[ i ][ k ] * B[ k ][ j ];
+ }
+ }
+ }
+
+ //! calculates ret= A_t*A
+ template <typename K, int rows, int cols>
+ static inline void multTransposedMatrix(const FieldMatrix<K,rows,cols> &matrix, FieldMatrix<K,cols,cols>& ret)
+ {
+ typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
+
+ for(size_type i=0; i<cols(); i++)
+ for(size_type j=0; j<cols(); j++)
+ {
+ ret[i][j]=0.0;
+ for(size_type k=0; k<rows(); k++)
+ ret[i][j]+=matrix[k][i]*matrix[k][j];
+ }
+ }
+#endif
+
+ //! calculates ret = matrix * x
+ template <typename MAT, typename V1, typename V2>
+ static inline void multAssign(const DenseMatrix<MAT> &matrix, const DenseVector<V1> & x, DenseVector<V2> & ret)
+ {
+ assert(x.size() == matrix.cols());
+ assert(ret.size() == matrix.rows());
+ typedef typename DenseMatrix<MAT>::size_type size_type;
+
+ for(size_type i=0; i<matrix.rows(); ++i)
+ {
+ ret[i] = 0.0;
+ for(size_type j=0; j<matrix.cols(); ++j)
+ {
+ ret[i] += matrix[i][j]*x[j];
+ }
+ }
+ }
+
+#if 0
+ //! calculates ret = matrix^T * x
+ template <typename K, int rows, int cols>
+ static inline void multAssignTransposed( const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,rows> & x, FieldVector<K,cols> & ret)
+ {
+ typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
+
+ for(size_type i=0; i<cols(); ++i)
+ {
+ ret[i] = 0.0;
+ for(size_type j=0; j<rows(); ++j)
+ ret[i] += matrix[j][i]*x[j];
+ }
+ }
+
+ //! calculates ret = matrix * x
+ template <typename K, int rows, int cols>
+ static inline FieldVector<K,rows> mult(const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,cols> & x)
+ {
+ FieldVector<K,rows> ret;
+ multAssign(matrix,x,ret);
+ return ret;
+ }
+
+ //! calculates ret = matrix^T * x
+ template <typename K, int rows, int cols>
+ static inline FieldVector<K,cols> multTransposed(const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,rows> & x)
+ {
+ FieldVector<K,cols> ret;
+ multAssignTransposed( matrix, x, ret );
+ return ret;
+ }
+#endif
+
+ } // end namespace DenseMatrixHelp
+
+ /** \brief Sends the matrix to an output stream */
+ template<typename MAT>
+ std::ostream& operator<< (std::ostream& s, const DenseMatrix<MAT>& a)
+ {
+ for (typename DenseMatrix<MAT>::size_type i=0; i<a.rows(); i++)
+ s << a[i] << std::endl;
+ return s;
+ }
+
+ /** @} end documentation */
+
+} // end namespace Dune
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_DENSEVECTOR_HH
+#define DUNE_DENSEVECTOR_HH
+
+#include <limits>
+
+#include "genericiterator.hh"
+#include "ftraits.hh"
+#include "matvectraits.hh"
+#include "promotiontraits.hh"
+#include "dotproduct.hh"
+
+namespace Dune {
+
+ // forward declaration of template
+ template<typename V> class DenseVector;
+
+ template<typename V>
+ struct FieldTraits< DenseVector<V> >
+ {
+ typedef typename FieldTraits< typename DenseMatVecTraits<V>::value_type >::field_type field_type;
+ typedef typename FieldTraits< typename DenseMatVecTraits<V>::value_type >::real_type real_type;
+ };
+
+ /** @defgroup DenseMatVec Dense Matrix and Vector Template Library
+ @ingroup Common
+ @{
+ */
+
+ /*! \file
+ * \brief Implements the dense vector interface, with an exchangeable storage class
+ */
+
+ namespace fvmeta
+ {
+ /**
+ \private
+ \memberof Dune::DenseVector
+ */
+ template<class K>
+ inline typename FieldTraits<K>::real_type absreal (const K& k)
+ {
+ return std::abs(k);
+ }
+
+ /**
+ \private
+ \memberof Dune::DenseVector
+ */
+ template<class K>
+ inline typename FieldTraits<K>::real_type absreal (const std::complex<K>& c)
+ {
+ return std::abs(c.real()) + std::abs(c.imag());
+ }
+
+ /**
+ \private
+ \memberof Dune::DenseVector
+ */
+ template<class K>
+ inline typename FieldTraits<K>::real_type abs2 (const K& k)
+ {
+ return k*k;
+ }
+
+ /**
+ \private
+ \memberof Dune::DenseVector
+ */
+ template<class K>
+ inline typename FieldTraits<K>::real_type abs2 (const std::complex<K>& c)
+ {
+ return c.real()*c.real() + c.imag()*c.imag();
+ }
+
+ /**
+ \private
+ \memberof Dune::DenseVector
+ */
+ template<class K, bool isInteger = std::numeric_limits<K>::is_integer>
+ struct Sqrt
+ {
+ static inline typename FieldTraits<K>::real_type sqrt (const K& k)
+ {
+ return std::sqrt(k);
+ }
+ };
+
+ /**
+ \private
+ \memberof Dune::DenseVector
+ */
+ template<class K>
+ struct Sqrt<K, true>
+ {
+ static inline typename FieldTraits<K>::real_type sqrt (const K& k)
+ {
+ return typename FieldTraits<K>::real_type(std::sqrt(double(k)));
+ }
+ };
+
+ /**
+ \private
+ \memberof Dune::DenseVector
+ */
+ template<class K>
+ inline typename FieldTraits<K>::real_type sqrt (const K& k)
+ {
+ return Sqrt<K>::sqrt(k);
+ }
+
+ }
+
+ /*! \brief Generic iterator class for dense vector and matrix implementations
+
+ provides sequential access to DenseVector, FieldVector and FieldMatrix
+ */
+ template<class C, class T>
+ class DenseIterator :
+ public Dune::RandomAccessIteratorFacade<DenseIterator<C,T>,T, T&, std::ptrdiff_t>
+ {
+ friend class DenseIterator<typename remove_const<C>::type, typename remove_const<T>::type >;
+ friend class DenseIterator<const typename remove_const<C>::type, const typename remove_const<T>::type >;
+
+ public:
+
+ /**
+ * @brief The type of the difference between two positions.
+ */
+ typedef std::ptrdiff_t DifferenceType;
+
+ /**
+ * @brief The type to index the underlying container.
+ */
+ typedef typename C::size_type SizeType;
+
+ // Constructors needed by the base iterators.
+ DenseIterator()
+ : container_(0), position_()
+ {}
+
+ DenseIterator(C& cont, SizeType pos)
+ : container_(&cont), position_(pos)
+ {}
+
+ DenseIterator(const DenseIterator<typename remove_const<C>::type, typename remove_const<T>::type >& other)
+ : container_(other.container_), position_(other.position_)
+ {}
+
+ // Methods needed by the forward iterator
+ bool equals(const DenseIterator<typename remove_const<C>::type,typename remove_const<T>::type>& other) const
+ {
+ return position_ == other.position_ && container_ == other.container_;
+ }
+
+
+ bool equals(const DenseIterator<const typename remove_const<C>::type,const typename remove_const<T>::type>& other) const
+ {
+ return position_ == other.position_ && container_ == other.container_;
+ }
+
+ T& dereference() const {
+ return container_->operator[](position_);
+ }
+
+ void increment(){
+ ++position_;
+ }
+
+ // Additional function needed by BidirectionalIterator
+ void decrement(){
+ --position_;
+ }
+
+ // Additional function needed by RandomAccessIterator
+ T& elementAt(DifferenceType i) const {
+ return container_->operator[](position_+i);
+ }
+
+ void advance(DifferenceType n){
+ position_=position_+n;
+ }
+
+ DifferenceType distanceTo(DenseIterator<const typename remove_const<C>::type,const typename remove_const<T>::type> other) const
+ {
+ assert(other.container_==container_);
+ return other.position_ - position_;
+ }
+
+ DifferenceType distanceTo(DenseIterator<typename remove_const<C>::type, typename remove_const<T>::type> other) const
+ {
+ assert(other.container_==container_);
+ return other.position_ - position_;
+ }
+
+ //! return index
+ SizeType index () const
+ {
+ return this->position_;
+ }
+
+ private:
+ C *container_;
+ SizeType position_;
+ };
+
+ /** \brief Interface for a class of dense vectors over a given field.
+ *
+ * \tparam V implementation class of the vector
+ * \tparam T value type
+ * \tparam S size type
+ *
+ * V has to provide the following members:
+ * @code
+ * T & _access (size_type);
+ * const T & _access (size_type) const;
+ * size_type _size () const;
+ * @endcode
+ */
+ template<typename V>
+ class DenseVector
+ {
+ typedef DenseMatVecTraits<V> Traits;
+ // typedef typename Traits::value_type K;
+
+ // Curiously recurring template pattern
+ V & asImp() { return static_cast<V&>(*this); }
+ const V & asImp() const { return static_cast<const V&>(*this); }
+
+ // prohibit copying
+ DenseVector ( const DenseVector & );
+
+ protected:
+ // construction allowed to derived classes only
+ DenseVector () {}
+
+ public:
+ //===== type definitions and constants
+
+ //! type of derived vector class
+ typedef typename Traits::derived_type derived_type;
+
+ //! export the type representing the field
+ typedef typename Traits::value_type value_type;
+
+ //! export the type representing the field
+ typedef typename Traits::value_type field_type;
+
+ //! export the type representing the components
+ typedef typename Traits::value_type block_type;
+
+ //! The type used for the index access and size operation
+ typedef typename Traits::size_type size_type;
+
+ //! We are at the leaf of the block recursion
+ enum {
+ //! The number of block levels we contain
+ blocklevel = 1
+ };
+
+ //===== assignment from scalar
+ //! Assignment operator for scalar
+ inline derived_type& operator= (const value_type& k)
+ {
+ for (size_type i=0; i<size(); i++)
+ asImp()[i] = k;
+ return asImp();
+ }
+
+ //===== access to components
+
+ //! random access
+ value_type & operator[] (size_type i)
+ {
+ return asImp().vec_access(i);
+ }
+
+ const value_type & operator[] (size_type i) const
+ {
+ return asImp().vec_access(i);
+ }
+
+ //! size method
+ size_type size() const
+ {
+ return asImp().vec_size();
+ }
+
+ //! Iterator class for sequential access
+ typedef DenseIterator<DenseVector,value_type> Iterator;
+ //! typedef for stl compliant access
+ typedef Iterator iterator;
+
+ //! begin iterator
+ Iterator begin ()
+ {
+ return Iterator(*this,0);
+ }
+
+ //! end iterator
+ Iterator end ()
+ {
+ return Iterator(*this,size());
+ }
+
+ //! @returns an iterator that is positioned before
+ //! the end iterator of the vector, i.e. at the last entry.
+ Iterator beforeEnd ()
+ {
+ return Iterator(*this,size()-1);
+ }
+
+ //! @returns an iterator that is positioned before
+ //! the first entry of the vector.
+ Iterator beforeBegin ()
+ {
+ return Iterator(*this,-1);
+ }
+
+ //! return iterator to given element or end()
+ Iterator find (size_type i)
+ {
+ return Iterator(*this,std::min(i,size()));
+ }
+
+ //! ConstIterator class for sequential access
+ typedef DenseIterator<const DenseVector,const value_type> ConstIterator;
+ //! typedef for stl compliant access
+ typedef ConstIterator const_iterator;
+
+ //! begin ConstIterator
+ ConstIterator begin () const
+ {
+ return ConstIterator(*this,0);
+ }
+
+ //! end ConstIterator
+ ConstIterator end () const
+ {
+ return ConstIterator(*this,size());
+ }
+
+ //! @returns an iterator that is positioned before
+ //! the end iterator of the vector. i.e. at the last element
+ ConstIterator beforeEnd () const
+ {
+ return ConstIterator(*this,size()-1);
+ }
+
+ //! @returns an iterator that is positioned before
+ //! the first entry of the vector.
+ ConstIterator beforeBegin () const
+ {
+ return ConstIterator(*this,-1);
+ }
+
+ //! return iterator to given element or end()
+ ConstIterator find (size_type i) const
+ {
+ return ConstIterator(*this,std::min(i,size()));
+ }
+
+ //===== vector space arithmetic
+
+ //! vector space addition
+ template <class Other>
+ derived_type& operator+= (const DenseVector<Other>& y)
+ {
+ assert(y.size() == size());
+ for (size_type i=0; i<size(); i++)
+ (*this)[i] += y[i];
+ return asImp();
+ }
+
+ //! vector space subtraction
+ template <class Other>
+ derived_type& operator-= (const DenseVector<Other>& y)
+ {
+ assert(y.size() == size());
+ for (size_type i=0; i<size(); i++)
+ (*this)[i] -= y[i];
+ return asImp();
+ }
+
+ //! Binary vector addition
+ template <class Other>
+ derived_type operator+ (const DenseVector<Other>& b) const
+ {
+ derived_type z = asImp();
+ return (z+=b);
+ }
+
+ //! Binary vector subtraction
+ template <class Other>
+ derived_type operator- (const DenseVector<Other>& b) const
+ {
+ derived_type z = asImp();
+ return (z-=b);
+ }
+
+ //! vector space add scalar to all comps
+ derived_type& operator+= (const value_type& k)
+ {
+ for (size_type i=0; i<size(); i++)
+ (*this)[i] += k;
+ return asImp();
+ }
+
+ //! vector space subtract scalar from all comps
+ derived_type& operator-= (const value_type& k)
+ {
+ for (size_type i=0; i<size(); i++)
+ (*this)[i] -= k;
+ return asImp();
+ }
+
+ //! vector space multiplication with scalar
+ derived_type& operator*= (const value_type& k)
+ {
+ for (size_type i=0; i<size(); i++)
+ (*this)[i] *= k;
+ return asImp();
+ }
+
+ //! vector space division by scalar
+ derived_type& operator/= (const value_type& k)
+ {
+ for (size_type i=0; i<size(); i++)
+ (*this)[i] /= k;
+ return asImp();
+ }
+
+ //! Binary vector comparison
+ template <class Other>
+ bool operator== (const DenseVector<Other>& y) const
+ {
+ assert(y.size() == size());
+ for (size_type i=0; i<size(); i++)
+ if ((*this)[i]!=y[i])
+ return false;
+
+ return true;
+ }
+
+ //! Binary vector incomparison
+ template <class Other>
+ bool operator!= (const DenseVector<Other>& y) const
+ {
+ return !operator==(y);
+ }
+
+
+ //! vector space axpy operation ( *this += a y )
+ template <class Other>
+ derived_type& axpy (const value_type& a, const DenseVector<Other>& y)
+ {
+ assert(y.size() == size());
+ for (size_type i=0; i<size(); i++)
+ (*this)[i] += a*y[i];
+ return asImp();
+ }
+
+ /**
+ * \brief indefinite vector dot product \f$\left (x^T \cdot y \right)\f$ which corresponds to Petsc's VecTDot
+ *
+ * http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Vec/VecTDot.html
+ * @param y other vector
+ * @return
+ */
+ template<class Other>
+ typename PromotionTraits<field_type,typename DenseVector<Other>::field_type>::PromotedType operator* (const DenseVector<Other>& y) const {
+ typedef typename PromotionTraits<field_type, typename DenseVector<Other>::field_type>::PromotedType PromotedType;
+ PromotedType result(0);
+ assert(y.size() == size());
+ for (size_type i=0; i<size(); i++) {
+ result += PromotedType((*this)[i]*y[i]);
+ }
+ return result;
+ }
+
+ /**
+ * @brief vector dot product \f$\left (x^H \cdot y \right)\f$ which corresponds to Petsc's VecDot
+ *
+ * http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Vec/VecDot.html
+ * @param y other vector
+ * @return
+ */
+ template<class Other>
+ typename PromotionTraits<field_type,typename DenseVector<Other>::field_type>::PromotedType dot(const DenseVector<Other>& y) const {
+ typedef typename PromotionTraits<field_type, typename DenseVector<Other>::field_type>::PromotedType PromotedType;
+ PromotedType result(0);
+ assert(y.size() == size());
+ for (size_type i=0; i<size(); i++) {
+ result += Dune::dot((*this)[i],y[i]);
+ }
+ return result;
+ }
+
+ //===== norms
+
+ //! one norm (sum over absolute values of entries)
+ typename FieldTraits<value_type>::real_type one_norm() const {
+ typename FieldTraits<value_type>::real_type result( 0 );
+ for (size_type i=0; i<size(); i++)
+ result += std::abs((*this)[i]);
+ return result;
+ }
+
+
+ //! simplified one norm (uses Manhattan norm for complex values)
+ typename FieldTraits<value_type>::real_type one_norm_real () const
+ {
+ typename FieldTraits<value_type>::real_type result( 0 );
+ for (size_type i=0; i<size(); i++)
+ result += fvmeta::absreal((*this)[i]);
+ return result;
+ }
+
+ //! two norm sqrt(sum over squared values of entries)
+ typename FieldTraits<value_type>::real_type two_norm () const
+ {
+ typename FieldTraits<value_type>::real_type result( 0 );
+ for (size_type i=0; i<size(); i++)
+ result += fvmeta::abs2((*this)[i]);
+ return fvmeta::sqrt(result);
+ }
+
+ //! square of two norm (sum over squared values of entries), need for block recursion
+ typename FieldTraits<value_type>::real_type two_norm2 () const
+ {
+ typename FieldTraits<value_type>::real_type result( 0 );
+ for (size_type i=0; i<size(); i++)
+ result += fvmeta::abs2((*this)[i]);
+ return result;
+ }
+
+ //! infinity norm (maximum of absolute values of entries)
+ typename FieldTraits<value_type>::real_type infinity_norm () const
+ {
+ if (size() == 0)
+ return 0.0;
+
+ ConstIterator it = begin();
+ typename FieldTraits<value_type>::real_type max = std::abs(*it);
+ for (it = it + 1; it != end(); ++it)
+ max = std::max(max, std::abs(*it));
+
+ return max;
+ }
+
+ //! simplified infinity norm (uses Manhattan norm for complex values)
+ typename FieldTraits<value_type>::real_type infinity_norm_real () const
+ {
+ if (size() == 0)
+ return 0.0;
+
+ ConstIterator it = begin();
+ typename FieldTraits<value_type>::real_type max = fvmeta::absreal(*it);
+ for (it = it + 1; it != end(); ++it)
+ max = std::max(max, fvmeta::absreal(*it));
+
+ return max;
+ }
+
+ //===== sizes
+
+ //! number of blocks in the vector (are of size 1 here)
+ size_type N () const
+ {
+ return size();
+ }
+
+ //! dimension of the vector space
+ size_type dim () const
+ {
+ return size();
+ }
+
+ };
+
+ /** \brief Write a DenseVector to an output stream
+ * \relates DenseVector
+ *
+ * \param[in] s std :: ostream to write to
+ * \param[in] v DenseVector to write
+ *
+ * \returns the output stream (s)
+ */
+ template<typename V>
+ std::ostream& operator<< (std::ostream& s, const DenseVector<V>& v)
+ {
+ for (typename DenseVector<V>::size_type i=0; i<v.size(); i++)
+ s << ((i>0) ? " " : "") << v[i];
+ return s;
+ }
+
+ /** @} end documentation */
+
+} // end namespace
+
+#endif // DUNE_DENSEVECTOR_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_DEPRECATED_HH
+#define DUNE_DEPRECATED_HH
+
+/** \file
+ * \brief Definition of the DUNE_DEPRECATED macro for the case that config.h
+ * is not available
+ */
+
+//! @addtogroup Common
+//! @{
+#if defined(DOXYGEN) || !defined(HAS_ATTRIBUTE_DEPRECATED)
+//! Mark some entity as deprecated
+/**
+ * \code
+ *#include <dune/common/deprecated.hh>
+ * \endcode
+ *
+ * This is a preprocessor define which can be used to mark functions,
+ * typedefs, enums and other stuff deprecated. If something is marked
+ * deprecated, users are advised to migrate to the new interface, since it
+ * will probably be removed in the next release of Dune.
+ *
+ * DUNE_DEPRECATED currently works with g++ and clang++. For other compilers it will
+ * be defined empty. This way the user will not get any deprecation warning,
+ * but at least his code still compiles (well, until the next Dune release,
+ * that is).
+ *
+ * Here are some examples how to mark different stuff deprecated:
+ * - Classes
+ * \code
+ class DUNE_DEPRECATED Class {}; // 1)
+ class Class {} DUNE_DEPRECATED; // 2)
+ * \endcode
+ * Both forms do not work properly with g++-4.1: no deprecation warning
+ * will be given, although the code still compiles. 1) should be preferred
+ * over 2) since 2) does not work with clang++-1.1 (again, no warning given
+ * but code still compiles, works with clang++-3.1)
+ * - Template classes
+ * \code
+ template<class T>
+ class DUNE_DEPRECATED Class {}; // 1)
+ template<class T>
+ class Class {} DUNE_DEPRECATED; // 2)
+ * \endcode
+ * This works works with g++ >=4.3 only; g++-4.1 and
+ * clang++ compile the code without warning in both cases. Furthermore,
+ * the warning is only triggered when copying an object of that template
+ * class, neither making a typedef nor simply creating such an object emit
+ * the warning. It is thus recommended that some essential class member be
+ * marked deprecated as well, if possible.
+ * - Member constants
+ * \code
+ template<typename T> struct Class {
+ static const int c0 DUNE_DEPRECATED = 0;
+ static const int DUNE_DEPRECATED c1 = 1;
+ };
+ * \endcode
+ * Works with g++-4.1, g++ >=4.3 and clang++3.1.
+ * No warning but clean compile with clang++-1.1.
+ * - Member enumerators
+ * \code
+ template<typename T> struct Class {
+ enum enumeration { enumerator = 0 };
+ };
+ * \endcode
+ * No form of deprecation is known that does not trigger an error on most
+ * compilers.
+ * - Member functions
+ * \code
+ template<typename T> struct Class {
+ void frob() DUNE_DEPRECATED {}
+ }; // 1)
+ template<typename T> struct Class {
+ void DUNE_DEPRECATED frob() {}
+ }; // 2)
+ template<typename T> struct Class {
+ DUNE_DEPRECATED void frob() {}
+ }; // 3)
+ * \endcode
+ * With g++ only 2) emits a warning for templated member functions.
+ */
+#define DUNE_DEPRECATED
+#else // defined(HAS_ATTRIBUTE_DEPRECATED)
+#define DUNE_DEPRECATED __attribute__((deprecated))
+#endif
+
+#if defined(DOXYGEN) || !defined(HAS_ATTRIBUTE_DEPRECATED_MSG)
+//! Mark some entity as deprecated
+/**
+ * \code
+ *#include <dune/common/deprecated.hh>
+ * \endcode
+ *
+ * This is a preprocessor define which can be used to mark functions,
+ * typedefs, enums and other stuff deprecated and to also specify a
+ * hint what replaces the given functionality. If something is marked
+ * deprecated, users are advised to migrate to the new interface,
+ * since it will probably be removed in the next release of Dune.
+ *
+ * DUNE_DEPRECATED_MSG currently works only for compilers which
+ * support the attribute __attribute__((deprecated("message")). For
+ * other compilers it will be defined empty. This way the user will
+ * not get any deprecation warning, but at least his code still
+ * compiles (well, until the next Dune release, that is).
+ *
+ * Here are some examples how to mark different stuff deprecated:
+ * - Classes
+ * \code
+ class DUNE_DEPRECATED_MSG("In the future, please use 'Glass'") Class {}; // 1)
+ class Class {} DUNE_DEPRECATED("In the future, please use 'Glass'"); // 2)
+ * \endcode
+ * For both forms, deprecation warnings and the additional hint "In
+ * the future, please use 'Glass'" will be printed on compilers
+ * which support it (e.g. G++ >= 4.5.0, clang++ >= 1.1). For compilers
+ * which support deprecating but do not take an additional hint
+ * (e.g. G++ < 4.5.0), only the deprecation warning is printed, and
+ * finally compilers which do not support deprecation of code won't
+ * print anything, but the code will still compile. 1) should be
+ * preferred over 2) since 2) does not work with clang++-1.1
+ * (again, no warning will be given but code still compiles)
+ * - Template classes
+ * \code
+ template<class T>
+ class DUNE_DEPRECATED_MSG("In the future, please use 'Glass'") Class {}; // 1)
+ template<class T>
+ class Class {} DUNE_DEPRECATED_MSG("In the future, please use 'Glass'"); // 2)
+ * \endcode
+ * This works works with g++ >= 4.5, clang++ until at least version
+ * 1.1 will compile the code without warning in both cases.
+ * Furthermore, the warning is only triggered when copying an
+ * object of that template class, neither making a typedef nor
+ * simply creating such an object emit the warning. It is thus
+ * recommended that some essential class member be marked
+ * deprecated as well, if possible.
+ * - Member constants
+ * \code
+ template<typename T> struct Class {
+ static const int c0 DUNE_DEPRECATED_MSG("c2 is the new hype") = 0;
+ static const int DUNE_DEPRECATED_MSG("c2 is the new hype") c1 = 1;
+ };
+ * \endcode
+ * Works without printing the hint on g++-4.1, g++-4.3, g++-4.4 and
+ * fully on g++ >= 4.5. Works for clang++-3.1.
+ * No warning but clean compile with clang++-1.1.
+ * - Member enumerators
+ * \code
+ template<typename T> struct Class {
+ enum enumeration { enumerator = 0 };
+ };
+ * \endcode
+ * No form of deprecation is known that does not trigger an error on most
+ * compilers.
+ * - Member functions
+ * \code
+ template<typename T> struct Class {
+ void frob() DUNE_DEPRECATED_MSG("use frog") {}
+ }; // 1)
+ template<typename T> struct Class {
+ void DUNE_DEPRECATED_MSG("use frog") frob() {}
+ }; // 2)
+ template<typename T> struct Class {
+ DUNE_DEPRECATED_MSG("use frog") void frob() {}
+ }; // 3)
+ * \endcode
+ * With g++ only 2) emits a warning for templated member functions.
+ */
+#define DUNE_DEPRECATED_MSG(text) DUNE_DEPRECATED
+#else // defined(HAS_ATTRIBUTE_DEPRECATED_MSG)
+#define DUNE_DEPRECATED_MSG(text) __attribute__((deprecated(# text)))
+#endif
+
+//! @}
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_DIAGONAL_MATRIX_HH
+#define DUNE_DIAGONAL_MATRIX_HH
+
+/*! \file
+ \brief This file implements a quadratic diagonal matrix of fixed size.
+ */
+
+#include <cassert>
+#include <cmath>
+#include <complex>
+#include <cstddef>
+#include <iostream>
+#include <memory>
+
+#include <dune/common/densematrix.hh>
+#include <dune/common/exceptions.hh>
+#include <dune/common/fmatrix.hh>
+#include <dune/common/fvector.hh>
+#include <dune/common/genericiterator.hh>
+#include <dune/common/typetraits.hh>
+#include <dune/common/unused.hh>
+
+
+namespace Dune {
+
+ template< class K, int n > class DiagonalRowVectorConst;
+ template< class K, int n > class DiagonalRowVector;
+ template< class DiagonalMatrixType > class DiagonalMatrixWrapper;
+ template< class C, class T, class R> class ContainerWrapperIterator;
+
+ /**
+ @addtogroup DenseMatVec
+ @{
+ */
+
+ /**
+ *@brief A diagonal matrix of static size.
+ *
+ * This is meant to be a replacement of FieldMatrix for the case that
+ * it is a diagonal matrix.
+ *
+ * \tparam K Type used for scalars
+ * \tparam n Matrix size
+ */
+ template<class K, int n>
+ class DiagonalMatrix
+ {
+ typedef DiagonalMatrixWrapper< DiagonalMatrix<K,n> > WrapperType;
+
+ public:
+ //===== type definitions and constants
+
+ //! export the type representing the field
+ typedef K value_type;
+ typedef value_type field_type;
+
+ //! export the type representing the components
+ typedef K block_type;
+
+ //! The type used for the index access and size operations.
+ typedef std::size_t size_type;
+
+ //! We are at the leaf of the block recursion
+ enum {
+ //! The number of block levels we contain. This is 1.
+ blocklevel = 1
+ };
+
+ //! Each row is implemented by a field vector
+ typedef DiagonalRowVector<K,n> row_type;
+ typedef row_type reference;
+ typedef row_type row_reference;
+ typedef DiagonalRowVectorConst<K,n> const_row_type;
+ typedef const_row_type const_reference;
+ typedef const_row_type const_row_reference;
+
+ //! export size
+ enum {
+ //! The number of rows
+ rows = n,
+ //! The number of columns
+ cols = n
+ };
+
+ //==== size
+
+ size_type size () const
+ {
+ return rows;
+ }
+
+ //===== constructors
+
+ //! Default constructor
+ DiagonalMatrix () {}
+
+ //! Constructor initializing the whole matrix with a scalar
+ DiagonalMatrix (const K& k)
+ : diag_(k)
+ {}
+
+ //! Constructor initializing the diagonal with a vector
+ DiagonalMatrix (const FieldVector<K,n>& diag)
+ : diag_(diag)
+ {}
+
+
+ /** \brief Assignment from a scalar */
+ DiagonalMatrix& operator= (const K& k)
+ {
+ diag_ = k;
+ return *this;
+ }
+
+ /** \brief Check if matrix is the same object as the other matrix */
+ bool identical(const DiagonalMatrix<K,n>& other) const
+ {
+ return (this==&other);
+ }
+
+ //===== iterator interface to rows of the matrix
+ //! Iterator class for sequential access
+ typedef ContainerWrapperIterator<const WrapperType, reference, reference> Iterator;
+ //! typedef for stl compliant access
+ typedef Iterator iterator;
+ //! rename the iterators for easier access
+ typedef Iterator RowIterator;
+ //! rename the iterators for easier access
+ typedef typename row_type::Iterator ColIterator;
+
+ //! begin iterator
+ Iterator begin ()
+ {
+ return Iterator(WrapperType(this),0);
+ }
+
+ //! end iterator
+ Iterator end ()
+ {
+ return Iterator(WrapperType(this),n);
+ }
+
+ //! @returns an iterator that is positioned before
+ //! the end iterator of the rows, i.e. at the last row.
+ Iterator beforeEnd ()
+ {
+ return Iterator(WrapperType(this),n-1);
+ }
+
+ //! @returns an iterator that is positioned before
+ //! the first row of the matrix.
+ Iterator beforeBegin ()
+ {
+ return Iterator(WrapperType(this),-1);
+ }
+
+
+ //! Iterator class for sequential access
+ typedef ContainerWrapperIterator<const WrapperType, const_reference, const_reference> ConstIterator;
+ //! typedef for stl compliant access
+ typedef ConstIterator const_iterator;
+ //! rename the iterators for easier access
+ typedef ConstIterator ConstRowIterator;
+ //! rename the iterators for easier access
+ typedef typename const_row_type::ConstIterator ConstColIterator;
+
+ //! begin iterator
+ ConstIterator begin () const
+ {
+ return ConstIterator(WrapperType(this),0);
+ }
+
+ //! end iterator
+ ConstIterator end () const
+ {
+ return ConstIterator(WrapperType(this),n);
+ }
+
+ //! @returns an iterator that is positioned before
+ //! the end iterator of the rows. i.e. at the last row.
+ ConstIterator beforeEnd() const
+ {
+ return ConstIterator(WrapperType(this),n-1);
+ }
+
+ //! @returns an iterator that is positioned before
+ //! the first row of the matrix.
+ ConstIterator beforeBegin () const
+ {
+ return ConstIterator(WrapperType(this),-1);
+ }
+
+
+
+ //===== vector space arithmetic
+
+ //! vector space addition
+ DiagonalMatrix& operator+= (const DiagonalMatrix& y)
+ {
+ diag_ += y.diag_;
+ return *this;
+ }
+
+ //! vector space subtraction
+ DiagonalMatrix& operator-= (const DiagonalMatrix& y)
+ {
+ diag_ -= y.diag_;
+ return *this;
+ }
+
+ //! vector space multiplication with scalar
+ DiagonalMatrix& operator+= (const K& k)
+ {
+ diag_ += k;
+ return *this;
+ }
+
+ //! vector space division by scalar
+ DiagonalMatrix& operator-= (const K& k)
+ {
+ diag_ -= k;
+ return *this;
+ }
+
+ //! vector space multiplication with scalar
+ DiagonalMatrix& operator*= (const K& k)
+ {
+ diag_ *= k;
+ return *this;
+ }
+
+ //! vector space division by scalar
+ DiagonalMatrix& operator/= (const K& k)
+ {
+ diag_ /= k;
+ return *this;
+ }
+
+ //===== comparison ops
+
+ //! comparison operator
+ bool operator==(const DiagonalMatrix& other) const
+ {
+ return diag_==other.diagonal();
+ }
+
+ //! incomparison operator
+ bool operator!=(const DiagonalMatrix& other) const
+ {
+ return diag_!=other.diagonal();
+ }
+
+
+ //===== linear maps
+
+ //! y = A x
+ template<class X, class Y>
+ void mv (const X& x, Y& y) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
+ if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
+#endif
+ for (size_type i=0; i<n; ++i)
+ y[i] = diag_[i] * x[i];
+ }
+
+ //! y = A^T x
+ template<class X, class Y>
+ void mtv (const X& x, Y& y) const
+ {
+ mv(x, y);
+ }
+
+ //! y += A x
+ template<class X, class Y>
+ void umv (const X& x, Y& y) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
+ if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
+#endif
+ for (size_type i=0; i<n; ++i)
+ y[i] += diag_[i] * x[i];
+ }
+
+ //! y += A^T x
+ template<class X, class Y>
+ void umtv (const X& x, Y& y) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
+ if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
+#endif
+ for (size_type i=0; i<n; ++i)
+ y[i] += diag_[i] * x[i];
+ }
+
+ //! y += A^H x
+ template<class X, class Y>
+ void umhv (const X& x, Y& y) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
+ if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
+#endif
+ for (size_type i=0; i<n; i++)
+ y[i] += conjugateComplex(diag_[i])*x[i];
+ }
+
+ //! y -= A x
+ template<class X, class Y>
+ void mmv (const X& x, Y& y) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
+ if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
+#endif
+ for (size_type i=0; i<n; ++i)
+ y[i] -= diag_[i] * x[i];
+ }
+
+ //! y -= A^T x
+ template<class X, class Y>
+ void mmtv (const X& x, Y& y) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
+ if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
+#endif
+ for (size_type i=0; i<n; ++i)
+ y[i] -= diag_[i] * x[i];
+ }
+
+ //! y -= A^H x
+ template<class X, class Y>
+ void mmhv (const X& x, Y& y) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
+ if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
+#endif
+ for (size_type i=0; i<n; i++)
+ y[i] -= conjugateComplex(diag_[i])*x[i];
+ }
+
+ //! y += alpha A x
+ template<class X, class Y>
+ void usmv (const K& alpha, const X& x, Y& y) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
+ if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
+#endif
+ for (size_type i=0; i<n; i++)
+ y[i] += alpha * diag_[i] * x[i];
+ }
+
+ //! y += alpha A^T x
+ template<class X, class Y>
+ void usmtv (const K& alpha, const X& x, Y& y) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
+ if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
+#endif
+ for (size_type i=0; i<n; i++)
+ y[i] += alpha * diag_[i] * x[i];
+ }
+
+ //! y += alpha A^H x
+ template<class X, class Y>
+ void usmhv (const K& alpha, const X& x, Y& y) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
+ if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
+#endif
+ for (size_type i=0; i<n; i++)
+ y[i] += alpha * conjugateComplex(diag_[i]) * x[i];
+ }
+
+ //===== norms
+
+ //! frobenius norm: sqrt(sum over squared values of entries)
+ double frobenius_norm () const
+ {
+ return diag_.two_norm();
+ }
+
+ //! square of frobenius norm, need for block recursion
+ double frobenius_norm2 () const
+ {
+ return diag_.two_norm2();
+ }
+
+ //! infinity norm (row sum norm, how to generalize for blocks?)
+ double infinity_norm () const
+ {
+ return diag_.infinity_norm();
+ }
+
+ //! simplified infinity norm (uses Manhattan norm for complex values)
+ double infinity_norm_real () const
+ {
+ return diag_.infinity_norm_real();
+ }
+
+
+
+ //===== solve
+
+ //! Solve system A x = b
+ template<class V>
+ void solve (V& x, const V& b) const
+ {
+ for (int i=0; i<n; i++)
+ x[i] = b[i]/diag_[i];
+ }
+
+ //! Compute inverse
+ void invert()
+ {
+ for (int i=0; i<n; i++)
+ diag_[i] = 1/diag_[i];
+ }
+
+ //! calculates the determinant of this matrix
+ K determinant () const
+ {
+ K det = diag_[0];
+ for (int i=1; i<n; i++)
+ det *= diag_[i];
+ return det;
+ }
+
+
+
+ //===== sizes
+
+ //! number of blocks in row direction
+ size_type N () const
+ {
+ return n;
+ }
+
+ //! number of blocks in column direction
+ size_type M () const
+ {
+ return n;
+ }
+
+
+
+ //===== query
+
+ //! return true when (i,j) is in pattern
+ bool exists (size_type i, size_type j) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (i<0 || i>=n) DUNE_THROW(FMatrixError,"row index out of range");
+ if (j<0 || j>=n) DUNE_THROW(FMatrixError,"column index out of range");
+#endif
+ return i==j;
+ }
+
+
+
+ //! Sends the matrix to an output stream
+ friend std::ostream& operator<< (std::ostream& s, const DiagonalMatrix<K,n>& a)
+ {
+ for (size_type i=0; i<n; i++) {
+ for (size_type j=0; j<n; j++)
+ s << ((i==j) ? a.diag_[i] : 0) << " ";
+ s << std::endl;
+ }
+ return s;
+ }
+
+ //! Return reference object as row replacement
+ reference operator[](size_type i)
+ {
+ return reference(const_cast<K*>(&diag_[i]), i);
+ }
+
+ //! Return const_reference object as row replacement
+ const_reference operator[](size_type i) const
+ {
+ return const_reference(const_cast<K*>(&diag_[i]), i);
+ }
+
+ //! Get const reference to diagonal entry
+ const K& diagonal(size_type i) const
+ {
+ return diag_[i];
+ }
+
+ //! Get reference to diagonal entry
+ K& diagonal(size_type i)
+ {
+ return diag_[i];
+ }
+
+ //! Get const reference to diagonal vector
+ const FieldVector<K,n>& diagonal() const
+ {
+ return diag_;
+ }
+
+ //! Get reference to diagonal vector
+ FieldVector<K,n>& diagonal()
+ {
+ return diag_;
+ }
+
+ private:
+
+ // the data, a FieldVector storing the diagonal
+ FieldVector<K,n> diag_;
+ };
+
+#ifndef DOXYGEN // hide specialization
+ /** \brief Special type for 1x1 matrices
+ */
+ template< class K >
+ class DiagonalMatrix<K, 1> : public FieldMatrix<K, 1, 1>
+ {
+ typedef FieldMatrix<K,1,1> Base;
+ public:
+ //! The type used for index access and size operations
+ typedef typename Base::size_type size_type;
+
+ //! We are at the leaf of the block recursion
+ enum {
+ //! The number of block levels we contain.
+ //! This is always one for this type.
+ blocklevel = 1
+ };
+
+ typedef typename Base::row_type row_type;
+
+ typedef typename Base::row_reference row_reference;
+ typedef typename Base::const_row_reference const_row_reference;
+
+ //! export size
+ enum {
+ //! \brief The number of rows.
+ //! This is always one for this type.
+ rows = 1,
+ //! \brief The number of columns.
+ //! This is always one for this type.
+ cols = 1
+ };
+
+
+ //! Default Constructor
+ DiagonalMatrix()
+ {}
+
+ //! Constructor initializing the whole matrix with a scalar
+ DiagonalMatrix(const K& scalar)
+ {
+ (*this)[0][0] = scalar;
+ }
+
+ //! Get const reference to diagonal entry
+ const K& diagonal(size_type) const
+ {
+ return (*this)[0][0];
+ }
+
+ //! Get reference to diagonal entry
+ K& diagonal(size_type)
+ {
+ return (*this)[0][0];
+ }
+
+ //! Get const reference to diagonal vector
+ const FieldVector<K,1>& diagonal() const
+ {
+ return (*this)[0];
+ }
+
+ //! Get reference to diagonal vector
+ FieldVector<K,1>& diagonal()
+ {
+ return (*this)[0];
+ }
+
+ };
+#endif
+
+
+ template<class DiagonalMatrixType>
+ class DiagonalMatrixWrapper
+ {
+ typedef typename DiagonalMatrixType::reference reference;
+ typedef typename DiagonalMatrixType::const_reference const_reference;
+ typedef typename DiagonalMatrixType::field_type K;
+ typedef DiagonalRowVector<K, DiagonalMatrixType::rows> row_type;
+ typedef std::size_t size_type;
+ typedef DiagonalMatrixWrapper< DiagonalMatrixType> MyType;
+
+ friend class ContainerWrapperIterator<const MyType, reference, reference>;
+ friend class ContainerWrapperIterator<const MyType, const_reference, const_reference>;
+
+ public:
+
+ DiagonalMatrixWrapper() :
+ mat_(0)
+ {}
+
+ DiagonalMatrixWrapper(const DiagonalMatrixType* mat) :
+ mat_(const_cast<DiagonalMatrixType*>(mat))
+ {}
+
+ size_type realIndex(int i) const
+ {
+ return i;
+ }
+
+ row_type* pointer(int i) const
+ {
+ row_ = row_type(&(mat_->diagonal(i)), i);
+ return &row_;
+ }
+
+ bool identical(const DiagonalMatrixWrapper& other) const
+ {
+ return mat_==other.mat_;
+ }
+
+ private:
+
+ mutable DiagonalMatrixType* mat_;
+ mutable row_type row_;
+ };
+
+ /** \brief
+ *
+ */
+ template< class K, int n >
+ class DiagonalRowVectorConst
+ {
+ template<class DiagonalMatrixType>
+ friend class DiagonalMatrixWrapper;
+ friend class ContainerWrapperIterator<DiagonalRowVectorConst<K,n>, const K, const K&>;
+
+ public:
+ // remember size of vector
+ enum { dimension = n };
+
+ // standard constructor and everything is sufficient ...
+
+ //===== type definitions and constants
+
+ //! export the type representing the field
+ typedef K field_type;
+
+ //! export the type representing the components
+ typedef K block_type;
+
+ //! The type used for the index access and size operation
+ typedef std::size_t size_type;
+
+ //! We are at the leaf of the block recursion
+ enum {
+ //! The number of block levels we contain
+ blocklevel = 1
+ };
+
+ //! export size
+ enum {
+ //! The size of this vector.
+ size = n
+ };
+
+ //! Constructor making uninitialized vector
+ DiagonalRowVectorConst() :
+ p_(0),
+ row_(0)
+ {}
+
+ //! Constructor making vector with identical coordinates
+ explicit DiagonalRowVectorConst (K* p, int col) :
+ p_(p),
+ row_(col)
+ {}
+
+ //===== access to components
+
+ //! same for read only access
+ const K& operator[] (size_type i) const
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (i!=row_)
+ DUNE_THROW(FMatrixError,"index is not contained in pattern");
+#else
+ DUNE_UNUSED_PARAMETER(i);
+#endif
+ return *p_;
+ }
+
+ // check if row is identical to other row (not only identical values)
+ // since this is a proxy class we need to check equality of the stored pointer
+ bool identical(const DiagonalRowVectorConst<K,n>& other) const
+ {
+ return ((p_ == other.p_)and (row_ == other.row_));
+ }
+
+ //! ConstIterator class for sequential access
+ typedef ContainerWrapperIterator<DiagonalRowVectorConst<K,n>, const K, const K&> ConstIterator;
+ //! typedef for stl compliant access
+ typedef ConstIterator const_iterator;
+
+ //! begin ConstIterator
+ ConstIterator begin () const
+ {
+ return ConstIterator(*this,0);
+ }
+
+ //! end ConstIterator
+ ConstIterator end () const
+ {
+ return ConstIterator(*this,1);
+ }
+
+ //! @returns an iterator that is positioned before
+ //! the end iterator of the rows. i.e. at the row.
+ ConstIterator beforeEnd() const
+ {
+ return ConstIterator(*this,0);
+ }
+
+ //! @returns an iterator that is positioned before
+ //! the first row of the matrix.
+ ConstIterator beforeBegin () const
+ {
+ return ConstIterator(*this,-1);
+ }
+
+ //! Binary vector comparison
+ bool operator== (const DiagonalRowVectorConst& y) const
+ {
+ return ((p_==y.p_)and (row_==y.row_));
+ }
+
+ //===== sizes
+
+ //! number of blocks in the vector (are of size 1 here)
+ size_type N () const
+ {
+ return n;
+ }
+
+ //! dimension of the vector space
+ size_type dim () const
+ {
+ return n;
+ }
+
+ //! index of this row in surrounding matrix
+ size_type rowIndex() const
+ {
+ return row_;
+ }
+
+ //! the diagonal value
+ const K& diagonal() const
+ {
+ return *p_;
+ }
+
+ protected:
+
+ size_type realIndex(int i) const
+ {
+ return rowIndex();
+ }
+
+ K* pointer(size_type i) const
+ {
+ return const_cast<K*>(p_);
+ }
+
+ DiagonalRowVectorConst* operator&()
+ {
+ return this;
+ }
+
+ // the data, very simply a pointer to the diagonal value and the row number
+ K* p_;
+ size_type row_;
+ };
+
+ template< class K, int n >
+ class DiagonalRowVector : public DiagonalRowVectorConst<K,n>
+ {
+ template<class DiagonalMatrixType>
+ friend class DiagonalMatrixWrapper;
+ friend class ContainerWrapperIterator<DiagonalRowVector<K,n>, K, K&>;
+
+ public:
+ // standard constructor and everything is sufficient ...
+
+ //===== type definitions and constants
+
+ //! export the type representing the field
+ typedef K field_type;
+
+ //! export the type representing the components
+ typedef K block_type;
+
+ //! The type used for the index access and size operation
+ typedef std::size_t size_type;
+
+ //! Constructor making uninitialized vector
+ DiagonalRowVector() : DiagonalRowVectorConst<K,n>()
+ {}
+
+ //! Constructor making vector with identical coordinates
+ explicit DiagonalRowVector (K* p, int col) : DiagonalRowVectorConst<K,n>(p, col)
+ {}
+
+ //===== assignment from scalar
+ //! Assignment operator for scalar
+ DiagonalRowVector& operator= (const K& k)
+ {
+ *p_ = k;
+ return *this;
+ }
+
+ //===== access to components
+
+ //! random access
+ K& operator[] (size_type i)
+ {
+#ifdef DUNE_FMatrix_WITH_CHECKING
+ if (i!=row_)
+ DUNE_THROW(FMatrixError,"index is contained in pattern");
+#endif
+ return *p_;
+ }
+
+ //! Iterator class for sequential access
+ typedef ContainerWrapperIterator<DiagonalRowVector<K,n>, K, K&> Iterator;
+ //! typedef for stl compliant access
+ typedef Iterator iterator;
+
+ //! begin iterator
+ Iterator begin ()
+ {
+ return Iterator(*this, 0);
+ }
+
+ //! end iterator
+ Iterator end ()
+ {
+ return Iterator(*this, 1);
+ }
+
+ //! @returns an iterator that is positioned before
+ //! the end iterator of the rows, i.e. at the last row.
+ Iterator beforeEnd ()
+ {
+ return Iterator(*this, 0);
+ }
+
+ //! @returns an iterator that is positioned before
+ //! the first row of the matrix.
+ Iterator beforeBegin ()
+ {
+ return Iterator(*this, -1);
+ }
+
+ //! ConstIterator class for sequential access
+ typedef ContainerWrapperIterator<DiagonalRowVectorConst<K,n>, const K, const K&> ConstIterator;
+ //! typedef for stl compliant access
+ typedef ConstIterator const_iterator;
+
+ using DiagonalRowVectorConst<K,n>::identical;
+ using DiagonalRowVectorConst<K,n>::operator[];
+ using DiagonalRowVectorConst<K,n>::operator==;
+ using DiagonalRowVectorConst<K,n>::begin;
+ using DiagonalRowVectorConst<K,n>::end;
+ using DiagonalRowVectorConst<K,n>::beforeEnd;
+ using DiagonalRowVectorConst<K,n>::beforeBegin;
+ using DiagonalRowVectorConst<K,n>::N;
+ using DiagonalRowVectorConst<K,n>::dim;
+ using DiagonalRowVectorConst<K,n>::rowIndex;
+ using DiagonalRowVectorConst<K,n>::diagonal;
+
+ protected:
+
+ DiagonalRowVector* operator&()
+ {
+ return this;
+ }
+
+ private:
+
+ using DiagonalRowVectorConst<K,n>::p_;
+ using DiagonalRowVectorConst<K,n>::row_;
+ };
+
+
+ // implement type traits
+ template<class K, int n>
+ struct const_reference< DiagonalRowVector<K,n> >
+ {
+ typedef DiagonalRowVectorConst<K,n> type;
+ };
+
+ template<class K, int n>
+ struct const_reference< DiagonalRowVectorConst<K,n> >
+ {
+ typedef DiagonalRowVectorConst<K,n> type;
+ };
+
+ template<class K, int n>
+ struct mutable_reference< DiagonalRowVector<K,n> >
+ {
+ typedef DiagonalRowVector<K,n> type;
+ };
+
+ template<class K, int n>
+ struct mutable_reference< DiagonalRowVectorConst<K,n> >
+ {
+ typedef DiagonalRowVector<K,n> type;
+ };
+
+
+
+ /** \brief Iterator class for sparse vector-like containers
+ *
+ * This class provides an iterator for sparse vector like containers.
+ * It contains a ContainerWrapper that must provide the translation
+ * from the position in the underlying container to the index
+ * in the sparse container.
+ *
+ * The ContainerWrapper must be default and copy-constructable.
+ * Furthermore it must provide the methods:
+ *
+ * bool identical(other) - check if this is identical to other (same container, not only equal)
+ * T* pointer(position) - get pointer to data at position in underlying container
+ * size_t realIndex(position) - get index in sparse container for position in underlying container
+ *
+ * Notice that the iterator stores a ContainerWrapper.
+ * This allows to use proxy classes as underlying container
+ * and as returned reference type.
+ *
+ * \tparam CW The container wrapper class
+ * \tparam T The contained type
+ * \tparam R The reference type returned by dereference
+ */
+ template<class CW, class T, class R>
+ class ContainerWrapperIterator : public BidirectionalIteratorFacade<ContainerWrapperIterator<CW,T,R>,T, R, int>
+ {
+ typedef typename remove_const<CW>::type NonConstCW;
+
+ friend class ContainerWrapperIterator<CW, typename mutable_reference<T>::type, typename mutable_reference<R>::type>;
+ friend class ContainerWrapperIterator<CW, typename const_reference<T>::type, typename const_reference<R>::type>;
+
+ typedef ContainerWrapperIterator<CW, typename mutable_reference<T>::type, typename mutable_reference<R>::type> MyType;
+ typedef ContainerWrapperIterator<CW, typename const_reference<T>::type, typename const_reference<R>::type> MyConstType;
+
+ public:
+
+ // Constructors needed by the facade iterators.
+ ContainerWrapperIterator() :
+ containerWrapper_(),
+ position_(0)
+ {}
+
+ ContainerWrapperIterator(CW containerWrapper, int position) :
+ containerWrapper_(containerWrapper),
+ position_(position)
+ {}
+
+ template<class OtherContainerWrapperIteratorType>
+ ContainerWrapperIterator(OtherContainerWrapperIteratorType& other) :
+ containerWrapper_(other.containerWrapper_),
+ position_(other.position_)
+ {}
+
+ ContainerWrapperIterator(const MyType& other) :
+ containerWrapper_(other.containerWrapper_),
+ position_(other.position_)
+ {}
+
+ ContainerWrapperIterator(const MyConstType& other) :
+ containerWrapper_(other.containerWrapper_),
+ position_(other.position_)
+ {}
+
+ template<class OtherContainerWrapperIteratorType>
+ ContainerWrapperIterator& operator=(OtherContainerWrapperIteratorType& other)
+ {
+ containerWrapper_ = other.containerWrapper_;
+ position_ = other.position_;
+ }
+
+ // This operator is needed since we can not get the address of the
+ // temporary object returned by dereference
+ T* operator->() const
+ {
+ return containerWrapper_.pointer(position_);
+ }
+
+ // Methods needed by the forward iterator
+ bool equals(const MyType& other) const
+ {
+ return position_ == other.position_ && containerWrapper_.identical(other.containerWrapper_);
+ }
+
+ bool equals(const MyConstType& other) const
+ {
+ return position_ == other.position_ && containerWrapper_.identical(other.containerWrapper_);
+ }
+
+ R dereference() const
+ {
+ return *containerWrapper_.pointer(position_);
+ }
+
+ void increment()
+ {
+ ++position_;
+ }
+
+ // Additional function needed by BidirectionalIterator
+ void decrement()
+ {
+ --position_;
+ }
+
+ // Additional function needed by RandomAccessIterator
+ R elementAt(int i) const
+ {
+ return *containerWrapper_.pointer(position_+i);
+ }
+
+ void advance(int n)
+ {
+ position_=position_+n;
+ }
+
+ template<class OtherContainerWrapperIteratorType>
+ std::ptrdiff_t distanceTo(OtherContainerWrapperIteratorType& other) const
+ {
+ assert(containerWrapper_.identical(other));
+ return other.position_ - position_;
+ }
+
+ std::ptrdiff_t index() const
+ {
+ return containerWrapper_.realIndex(position_);
+ }
+
+ private:
+ NonConstCW containerWrapper_;
+ size_t position_;
+ };
+
+
+
+ template<class M, class K, int n>
+ void istl_assign_to_fmatrix(DenseMatrix<M>& fm, const DiagonalMatrix<K,n>& s)
+ {
+ assert( fm.rows() == n );
+ assert( fm.cols() == n );
+ fm = K();
+ for(int i=0; i<n; ++i)
+ fm[i][i] = s.diagonal()[i];
+ }
+ /* @} */
+} // end namespace
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+
+#ifndef DUNE_COMMON_DOCUMENTATION_HH
+#define DUNE_COMMON_DOCUMENTATION_HH
+
+/** \file
+ \brief Documentation related stuff
+ */
+
+namespace Dune {
+
+ /**
+ * \brief Dummy struct used for documentation purposes
+ *
+ * This struct can be used for documenting interfaces. One example would
+ * be:
+ * \code
+ * // Traits class that determines some property for some other type T
+ * template<class T>
+ * class SomeTraits {
+ * dune_static_assert(AlwaysFalse<T>::value,
+ * "Sorry, SomeTraits must be specialized for all types");
+ * public:
+ * // The type of some property of T
+ * typedef ImplementationDefined type;
+ * };
+ * #ifndef DOXYGEN
+ * template<>
+ * struct SomeTraits<int>
+ * typedef ... type;
+ * };
+ * // ...
+ * #endif // DOXYGEN
+ * \endcode
+ *
+ * \sa implementationDefined
+ */
+ struct ImplementationDefined {};
+
+ /**
+ * \brief Dummy integral value used for documentation purposes
+ *
+ * \var Dune::implementationDefined
+ * \code
+ * #include <dune/common/documentation.hh>
+ * \endcode
+ *
+ * \sa ImplementationDefined
+ */
+ enum { implementationDefined };
+
+}
+
+
+#endif // DUNE_COMMON_DOCUMENTATION_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_DOTPRODUCT_HH
+#define DUNE_DOTPRODUCT_HH
+
+#include "ftraits.hh"
+#include "typetraits.hh"
+#include "promotiontraits.hh"
+
+namespace Dune {
+ /**
+ * @file
+ * @brief Provides the functions dot(a,b) := \f$a^H \cdot b \f$ and dotT(a,b) := \f$a^T \cdot b \f$
+ *
+ * The provided dot products dot,dotT are used to compute (indefinite) dot products for fundamental types as well as DUNE vector types, such as DenseVector, FieldVector, ISTLVector.
+ * Note that the definition of dot(a,b) conjugates the first argument. This agrees with the behvaior of Matlab and Petsc, but noch with BLAS.
+ * @author Jö Fahlke, Matthias Wohlmuth
+ */
+
+ /** @addtogroup Common
+ *
+ * @{
+ */
+
+ template<class T>
+ struct AlwaysVoid { typedef void type; };
+
+ template<class T, class = void>
+ struct IsVector : false_type {};
+
+ template<class T>
+ struct IsVector<T, typename AlwaysVoid<typename T::field_type>::type>
+ : true_type {};
+
+ /** @brief computes the dot product for fundamental data types according to Petsc's VectDot function: dot(a,b) := std::conj(a)*b
+ *
+ * @see http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Vec/VecDot.html#VecDot
+ * @param a
+ * @param b
+ * @return conj(a)*b
+ */
+ template<class A, class B>
+ inline typename enable_if<!IsVector<A>::value && !is_same<typename FieldTraits<A>::field_type,typename FieldTraits<A>::real_type> ::value, typename PromotionTraits<A,B>::PromotedType>::type
+ dot(const A & a, const B & b) {
+ return conj(a)*b;
+ }
+
+ /**
+ * @brief computes the dot product for fundamental data types according to Petsc's VectDot function: dot(a,b) := std::conj(a)*b
+ *
+ * Specialization for real first arguments which replaces conj(a) by a.
+ * @see http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Vec/VecTDot.html#VecTDot
+ * @param a
+ * @param b
+ * @return a*b (which is the same as conj(a)*b in this case)
+ */
+ // fundamental type with A being a real type
+ template<class A, class B>
+ inline typename enable_if<!IsVector<A>::value && is_same<typename FieldTraits<A>::field_type,typename FieldTraits<A>::real_type>::value, typename PromotionTraits<A,B>::PromotedType>::type
+ dot(const A & a, const B & b) {
+ return a*b;
+ }
+
+ /**
+ * @brief computes the dot product for various dune vector types according to Petsc's VectDot function: dot(a,b) := std::conj(a)*b
+ *
+ * Specialization for real first arguments which replaces conj(a) by a.
+ * @see http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Vec/VecTDot.html#VecTDot
+ * @param a
+ * @param b
+ * @return dot(a,b)
+ */
+ // vectors
+ template<typename A, typename B>
+ // inline typename enable_if<IsVector<A>::value, typename PromotionTraits<typename FieldTraits<A>::field_type, typename FieldTraits<B>::field_type >::PromotedType>::type
+ inline typename enable_if<IsVector<A>::value, typename PromotionTraits<typename A::field_type, typename B::field_type >::PromotedType>::type
+ dot(const A & a, const B & b) {
+ return a.dot(b);
+ }
+ /** @} */
+
+ /**
+ * @brief Computes an indefinite vector dot product for fundamental data types according to Petsc's VectTDot function: dotT(a,b) := a*b
+ * @see http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Vec/VecTDot.html#VecTDot
+ * @param a
+ * @param b
+ * @return a*b
+ */
+ template<class A, class B>
+ inline typename enable_if<!IsVector<A>::value && !is_same<typename FieldTraits<A>::field_type,typename FieldTraits<A>::real_type> ::value, typename PromotionTraits<A,B>::PromotedType>::type
+ dotT(const A & a, const B & b) {
+ return a*b;
+ }
+
+ /**
+ * @brief Computes an indefinite vector dot product for various dune vector types according to Petsc's VectTDot function: dotT(a,b) := a*b
+ * @see http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Vec/VecTDot.html#VecTDot
+ * @param a
+ * @param b
+ * @return a*b
+ */
+ template<class A, class B>
+ inline typename enable_if<IsVector<A>::value, typename PromotionTraits<typename A::field_type, typename B::field_type >::PromotedType>::type
+ dotT(const A & a, const B & b) {
+ return a*b;
+ }
+
+ /** @} */
+} // end namespace DUNE
+
+#endif // DUNE_DOTPRODUCT_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id: fmatrix.hh 6181 2010-10-13 18:53:40Z christi $
+#ifndef DUNE_DYNMATRIX_HH
+#define DUNE_DYNMATRIX_HH
+
+#include <cmath>
+#include <cstddef>
+#include <iostream>
+
+#include <dune/common/exceptions.hh>
+#include <dune/common/dynvector.hh>
+#include <dune/common/densematrix.hh>
+#include <dune/common/static_assert.hh>
+
+namespace Dune
+{
+
+ /**
+ @addtogroup DenseMatVec
+ @{
+ */
+
+ /*! \file
+ * \brief This file implements a dense matrix with dynamic numbers of rows and columns.
+ */
+
+ template< class K > class DynamicMatrix;
+
+ template< class K >
+ struct DenseMatVecTraits< DynamicMatrix<K> >
+ {
+ typedef DynamicMatrix<K> derived_type;
+
+ typedef DynamicVector<K> row_type;
+
+ typedef row_type &row_reference;
+ typedef const row_type &const_row_reference;
+
+ typedef std::vector<K> container_type;
+ typedef K value_type;
+ typedef typename container_type::size_type size_type;
+ };
+
+ template< class K >
+ struct FieldTraits< DynamicMatrix<K> >
+ {
+ typedef typename FieldTraits<K>::field_type field_type;
+ typedef typename FieldTraits<K>::real_type real_type;
+ };
+
+ /** \brief Construct a matrix with a dynamic size.
+ *
+ * \tparam K is the field type (use float, double, complex, etc)
+ */
+ template<class K>
+ class DynamicMatrix : public DenseMatrix< DynamicMatrix<K> >
+ {
+ std::vector< DynamicVector<K> > _data;
+ typedef DenseMatrix< DynamicMatrix<K> > Base;
+ public:
+ typedef typename Base::size_type size_type;
+ typedef typename Base::value_type value_type;
+ typedef typename Base::row_type row_type;
+
+ //===== constructors
+ //! \brief Default constructor
+ DynamicMatrix () {}
+
+ //! \brief Constructor initializing the whole matrix with a scalar
+ DynamicMatrix (size_type r, size_type c, value_type v = value_type() ) :
+ _data(r, row_type(c, v) )
+ {}
+
+ //==== resize related methods
+ void resize (size_type r, size_type c, value_type v = value_type() )
+ {
+ _data.resize(0);
+ _data.resize(r, row_type(c, v) );
+ }
+
+ //===== assignment
+ using Base::operator=;
+
+ // make this thing a matrix
+ size_type mat_rows() const { return _data.size(); }
+ size_type mat_cols() const {
+ assert(this->rows());
+ return _data.front().size();
+ }
+ row_type & mat_access(size_type i) { return _data[i]; }
+ const row_type & mat_access(size_type i) const { return _data[i]; }
+ };
+
+ /** @} end documentation */
+
+} // end namespace
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_FMATRIXEIGENVALUES_EXT_CC
+#define DUNE_FMATRIXEIGENVALUES_EXT_CC
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <iostream>
+#include <cmath>
+#include <cassert>
+
+#include <dune/common/exceptions.hh>
+
+#if HAVE_LAPACK
+
+// nonsymmetric matrices
+#define DGEEV_FORTRAN FC_FUNC (dgeev, DGEEV)
+
+// dsyev declaration (in liblapack)
+extern "C" {
+
+ /*
+ *
+ ** purpose
+ ** =======
+ **
+ ** xgeev computes for an N-by-N BASE DATA TYPE nonsymmetric matrix A, the
+ ** eigenvalues and, optionally, the left and/or right eigenvectors.
+ **
+ ** The right eigenvector v(j) of A satisfies
+ ** A * v(j) = lambda(j) * v(j)
+ ** where lambda(j) is its eigenvalue.
+ ** The left eigenvector u(j) of A satisfies
+ ** u(j)**T * A = lambda(j) * u(j)**T
+ ** where u(j)**T denotes the transpose of u(j).
+ **
+ ** The computed eigenvectors are normalized to have Euclidean norm
+ ** equal to 1 and largest component real.
+ **
+ ** arguments
+ ** =========
+ **
+ ** jobvl (input) char
+ ** = 'n': left eigenvectors of a are not computed;
+ ** = 'v': left eigenvectors of a are computed.
+ **
+ ** jobvr (input) char
+ ** = 'n': right eigenvectors of a are not computed;
+ ** = 'v': right eigenvectors of a are computed.
+ **
+ ** n (input) long int
+ ** the order of the matrix v. v >= 0.
+ **
+ ** a (input/output) BASE DATA TYPE array, dimension (lda,n)
+ ** on entry, the n-by-n matrix a.
+ ** on exit, a has been overwritten.
+ **
+ ** lda (input) long int
+ ** the leading dimension of the array a. lda >= max(1,n).
+ **
+ ** wr (output) BASE DATA TYPE array, dimension (n)
+ ** wi (output) BASE DATA TYPE array, dimension (n)
+ ** wr and wi contain the real and imaginary parts,
+ ** respectively, of the computed eigenvalues. complex
+ ** conjugate pairs of eigenvalues appear consecutively
+ ** with the eigenvalue having the positive imaginary part
+ ** first.
+ **
+ ** vl (output) COMPLEX DATA TYPE array, dimension (ldvl,n)
+ ** if jobvl = 'v', the left eigenvectors u(j) are stored one
+ ** after another in the columns of vl, in the same order
+ ** as their eigenvalues.
+ ** if jobvl = 'n', vl is not referenced.
+ ** if the j-th eigenvalue is real, then u(j) = vl(:,j),
+ ** the j-th column of vl.
+ ** if the j-th and (j+1)-st eigenvalues form a complex
+ ** conjugate pair, then u(j) = vl(:,j) + i*vl(:,j+1) and
+ ** u(j+1) = vl(:,j) - i*vl(:,j+1).
+ **
+ ** ldvl (input) long int
+ ** the leading dimension of the array vl. ldvl >= 1; if
+ ** jobvl = 'v', ldvl >= n.
+ **
+ ** vr (output) COMPLEX DATA TYPE array, dimension (ldvr,n)
+ ** if jobvr = 'v', the right eigenvectors v(j) are stored one
+ ** after another in the columns of vr, in the same order
+ ** as their eigenvalues.
+ ** if jobvr = 'n', vr is not referenced.
+ ** if the j-th eigenvalue is real, then v(j) = vr(:,j),
+ ** the j-th column of vr.
+ ** if the j-th and (j+1)-st eigenvalues form a complex
+ ** conjugate pair, then v(j) = vr(:,j) + i*vr(:,j+1) and
+ ** v(j+1) = vr(:,j) - i*vr(:,j+1).
+ **
+ ** ldvr (input) long int
+ ** the leading dimension of the array vr. ldvr >= 1; if
+ ** jobvr = 'v', ldvr >= n.
+ **
+ ** work (workspace/output) BASE DATA TYPE array, dimension (max(1,lwork))
+ ** on exit, if info = 0, work(1) returns the optimal lwork.
+ **
+ ** lwork (input) long int
+ ** the dimension of the array work. lwork >= max(1,3*n), and
+ ** if jobvl = 'v' or jobvr = 'v', lwork >= 4*n. for good
+ ** performance, lwork must generally be larger.
+ **
+ ** if lwork = -1, then a workspace query is assumed; the routine
+ ** only calculates the optimal size of the work array, returns
+ ** this value as the first entry of the work array, and no error
+ ** message related to lwork is issued by xerbla.
+ **
+ ** info (output) long int
+ ** = 0: successful exit
+ ** < 0: if info = -i, the i-th argument had an illegal value.
+ ** > 0: if info = i, the qr algorithm failed to compute all the
+ ** eigenvalues, and no eigenvectors have been computed;
+ ** elements i+1:n of wr and wi contain eigenvalues which
+ ** have converged.
+ **
+ **/
+
+ extern void DGEEV_FORTRAN(const char* jobvl, const char* jobvr, const long
+ int* n, double* a, const long int* lda, double* wr, double* wi, double* vl,
+ const long int* ldvl, double* vr, const long int* ldvr, double* work,
+ const long int* lwork, const long int* info);
+
+} // end extern C
+#endif
+
+namespace Dune {
+
+ namespace DynamicMatrixHelp {
+
+ void eigenValuesNonsymLapackCall(
+ const char* jobvl, const char* jobvr, const long
+ int* n, double* a, const long int* lda, double* wr, double* wi, double* vl,
+ const long int* ldvl, double* vr, const long int* ldvr, double* work,
+ const long int* lwork, const long int* info)
+ {
+#if HAVE_LAPACK
+ // call LAPACK dgeev
+ DGEEV_FORTRAN(jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr, ldvr,
+ work, lwork, info);
+#else
+ DUNE_THROW(NotImplemented,"eigenValuesNonsymLapackCall: LAPACK not found!");
+#endif
+ }
+
+ } // end namespace FMatrixHelp
+
+} // end namespace Dune
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_DYNMATRIXEIGENVALUES_HH
+#define DUNE_DYNMATRIXEIGENVALUES_HH
+
+#include "dynmatrix.hh"
+
+/*!
+ \file
+ \brief utility functions to compute eigenvalues for
+ dense matrices.
+ \addtogroup DenseMatVec
+ @{
+ */
+
+namespace Dune {
+
+ namespace DynamicMatrixHelp {
+
+ // defined in fmatrixev_ext.cpp
+ extern void eigenValuesNonsymLapackCall(
+ const char* jobvl, const char* jobvr, const long
+ int* n, double* a, const long int* lda, double* wr, double* wi, double* vl,
+ const long int* ldvl, double* vr, const long int* ldvr, double* work,
+ const long int* lwork, const long int* info);
+
+ /** \brief calculates the eigenvalues of a symmetric field matrix
+ \param[in] matrix matrix eigenvalues are calculated for
+ \param[out] eigenValues FieldVector that contains eigenvalues in
+ ascending order
+
+ \note LAPACK::dgeev is used to calculate the eigen values
+ */
+ template <typename K, class C>
+ static void eigenValuesNonSym(const DynamicMatrix<K>& matrix,
+ DynamicVector<C>& eigenValues)
+ {
+ {
+ const long int N = matrix.rows();
+ const char jobvl = 'n';
+ const char jobvr = 'n';
+
+
+ // matrix to put into dgeev
+ double matrixVector[N * N];
+
+ // copy matrix
+ int row = 0;
+ for(int i=0; i<N; ++i)
+ {
+ for(int j=0; j<N; ++j, ++row)
+ {
+ matrixVector[ row ] = matrix[ i ][ j ];
+ }
+ }
+
+ // working memory
+ double eigenR[N];
+ double eigenI[N];
+ double work[3*N];
+
+ // return value information
+ long int info = 0;
+ long int lwork = 3*N;
+
+ // call LAPACK routine (see fmatrixev_ext.cc)
+ eigenValuesNonsymLapackCall(&jobvl, &jobvr, &N, &matrixVector[0], &N,
+ &eigenR[0], &eigenI[0], 0, &N, 0, &N, &work[0],
+ &lwork, &info);
+
+ if( info != 0 )
+ {
+ std::cerr << "For matrix " << matrix << " eigenvalue calculation failed! " << std::endl;
+ DUNE_THROW(InvalidStateException,"eigenValues: Eigenvalue calculation failed!");
+ }
+ for (int i=0; i<N; ++i)
+ eigenValues[i] = std::complex<double>(eigenR[i], eigenI[i]);
+ }
+ }
+
+ }
+
+}
+/** @} */
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id: fvector.hh 6105 2010-08-25 16:06:36Z christi $
+#ifndef DUNE_DYNVECTOR_HH
+#define DUNE_DYNVECTOR_HH
+
+#include <cmath>
+#include <cstddef>
+#include <cstdlib>
+#include <complex>
+#include <cstring>
+#include <limits>
+
+#include "exceptions.hh"
+#include "genericiterator.hh"
+
+#include <vector>
+#include "densevector.hh"
+
+namespace Dune {
+
+ /** @addtogroup DenseMatVec
+ @{
+ */
+
+ /*! \file
+ * \brief This file implements a dense vector with a dynamic size.
+ */
+
+ template< class K > class DynamicVector;
+ template< class K >
+ struct DenseMatVecTraits< DynamicVector<K> >
+ {
+ typedef DynamicVector<K> derived_type;
+ typedef std::vector<K> container_type;
+ typedef K value_type;
+ typedef typename container_type::size_type size_type;
+ };
+
+ template< class K >
+ struct FieldTraits< DynamicVector<K> >
+ {
+ typedef typename FieldTraits<K>::field_type field_type;
+ typedef typename FieldTraits<K>::real_type real_type;
+ };
+
+ /** \brief Construct a vector with a dynamic size.
+ *
+ * \tparam K is the field type (use float, double, complex, etc)
+ */
+ template< class K >
+ class DynamicVector : public DenseVector< DynamicVector<K> >
+ {
+ std::vector<K> _data;
+
+ typedef DenseVector< DynamicVector<K> > Base;
+ public:
+ typedef typename Base::size_type size_type;
+ typedef typename Base::value_type value_type;
+
+ //! Constructor making uninitialized vector
+ DynamicVector() {}
+
+ //! Constructor making vector with identical coordinates
+ explicit DynamicVector (size_type n, value_type c = value_type() ) :
+ _data(n,c)
+ {}
+
+ //! Constructor making vector with identical coordinates
+ DynamicVector (const DynamicVector & x) :
+ _data(x._data)
+ {}
+
+ using Base::operator=;
+
+ //==== forward some methods of std::vector
+ /** \brief Number of elements for which memory has been allocated.
+
+ capacity() is always greater than or equal to size().
+ */
+ size_type capacity() const
+ {
+ return _data.capacity();
+ }
+ void resize (size_type n, value_type c = value_type() )
+ {
+ _data.resize(n,c);
+ }
+ void reserve (size_type n)
+ {
+ _data.reserve(n);
+ }
+
+ //==== make this thing a vector
+ size_type vec_size() const { return _data.size(); }
+ K & vec_access(size_type i) { return _data[i]; }
+ const K & vec_access(size_type i) const { return _data[i]; }
+ };
+
+ /** \brief Read a DynamicVector from an input stream
+ * \relates DynamicVector
+ *
+ * \note This operator is STL compilant, i.e., the content of v is only
+ * changed if the read operation is successful.
+ *
+ * \param[in] in std :: istream to read from
+ * \param[out] v DynamicVector to be read
+ *
+ * \returns the input stream (in)
+ */
+ template<class K>
+ inline std::istream &operator>> ( std::istream &in,
+ DynamicVector<K> &v )
+ {
+ DynamicVector<K> w(v);
+ for( typename DynamicVector<K>::size_type i = 0; i < w.size(); ++i )
+ in >> w[ i ];
+ if(in)
+ v = w;
+ return in;
+ }
+
+ /** @} end documentation */
+
+} // end namespace
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_ENUMSET_HH
+#define DUNE_ENUMSET_HH
+
+#include <iostream>
+#include <dune/common/unused.hh>
+
+namespace Dune
+{
+ /**
+ * @file
+ * @brief Classes for building sets out of enumeration values.
+ * @author Markus Blatt
+ */
+ /** @addtogroup Common
+ *
+ * @{
+ */
+
+ /**
+ * @brief An empty set.
+ */
+ template<typename TA>
+ class EmptySet
+ {
+ public:
+ /**
+ * @brief The POD type the set holds.
+ */
+ typedef TA Type;
+ /**
+ * @brief Always returns false.
+ */
+ static bool contains(const Type& attribute);
+ };
+
+ /**
+ * @brief A set containing everything.
+ */
+ template<typename TA>
+ class AllSet
+ {
+ public:
+ /**
+ * @brief The POD type the set holds.
+ */
+ typedef TA Type;
+ /**
+ * @brief Always returns false.
+ */
+ static bool contains(const Type& attribute);
+ };
+
+ /**
+ * @brief A set consisting only of one item.
+ */
+ template<typename TA, int item>
+ class EnumItem
+ {
+ public:
+ /**
+ * @brief The type the set holds.
+ */
+ typedef TA Type;
+
+ /**
+ * @brief Tests whether an item is in the set.
+ * @return True if item==Type.
+ */
+ static bool contains(const Type& attribute);
+ };
+
+ /**
+ * @brief A set representing a range including the borders.
+ */
+ template<typename TA,int from, int end>
+ class EnumRange //: public PODSet<EnumRange<T,from,end>,T>
+ {
+ public:
+ /**
+ * @brief The type the set holds.
+ */
+ typedef TA Type;
+ static bool contains(const Type& item);
+ };
+
+ /**
+ * @brief The negation of a set.
+ * An item is contained in the set if and only if it is not
+ * contained in the negated set.
+ */
+ template<typename S>
+ class NegateSet
+ {
+ public:
+ typedef typename S::Type Type;
+
+ static bool contains(const Type& item)
+ {
+ return !S::contains(item);
+ }
+ };
+
+ /**
+ * @brief A set combining two other sets.
+ */
+ template<class TI1, class TI2, typename TA=typename TI1::Type>
+ class Combine
+ {
+ public:
+ static bool contains(const TA& item);
+ };
+
+ template<typename TA>
+ inline bool EmptySet<TA>::contains(const Type& attribute)
+ {
+ DUNE_UNUSED_PARAMETER(attribute);
+ return false;
+ }
+
+ template<typename TA>
+ inline bool AllSet<TA>::contains(const Type& attribute)
+ {
+ DUNE_UNUSED_PARAMETER(attribute);
+ return true;
+ }
+
+ template<typename TA,int i>
+ inline bool EnumItem<TA,i>::contains(const Type& item)
+ {
+ return item==i;
+ }
+
+ template<typename TA,int i>
+ inline std::ostream& operator<<(std::ostream& os, const EnumItem<TA,i>&)
+ {
+ return os<<i;
+ }
+
+ template<typename TA, int from, int to>
+ inline bool EnumRange<TA,from,to>::contains(const Type& item)
+ {
+ return from<=item && item<=to;
+ }
+
+ template<typename TA, int from, int to>
+ inline std::ostream& operator<<(std::ostream& os, const EnumRange<TA,from,to>&)
+ {
+ return os<<"["<<from<<" - "<<to<<"]";
+ }
+
+ template<class TI1, class TI2, typename TA>
+ inline bool Combine<TI1,TI2,TA>::contains(const TA& item)
+ {
+ return TI1::contains(item) ||
+ TI2::contains(item);
+ }
+
+ template<class TI1, class TI2>
+ inline Combine<TI1,TI2,typename TI1::Type> combine(const TI1& set1, const TI2& set2)
+ {
+ return Combine<TI1,TI2,typename TI1::Type>();
+ }
+
+ template<class TI1, class TI2, class T>
+ inline std::ostream& operator<<(std::ostream& os, const Combine<TI1,TI2,T>&)
+ {
+ return os << TI1()<<" "<<TI2();
+ }
+ /** @} */
+}
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#include <dune/common/exceptions.hh>
+
+namespace Dune {
+ // static member of Dune::Exception
+ ExceptionHook * Exception::_hook = 0;
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+
+#ifndef DUNE_EXCEPTIONS_HH
+#define DUNE_EXCEPTIONS_HH
+
+#include <string>
+#include <sstream>
+
+namespace Dune {
+
+ /*! \defgroup Exceptions Exception handling
+ \ingroup Common
+ \{
+
+ The Dune-exceptions are designed to allow a simple derivation of subclasses
+ and to accept a text written in the '<<' syntax.
+
+ Example of usage:
+
+ \code
+ #include <dune/common/exceptions.hh>
+
+ ...
+
+ class FileNotFoundError : public Dune::IOError {};
+
+ ...
+
+ void fileopen (std::string name) {
+ std::ifstream file;
+
+ file.open(name.c_str());
+
+ if (file == 0)
+ DUNE_THROW(FileNotFoundError, "File " << name << " not found!");
+
+ ...
+
+ file.close();
+ }
+
+ ...
+
+ int main () {
+ try {
+ ...
+ } catch (Dune::IOError &e) {
+ std::cerr << "I/O error: " << e << std::endl;
+ return 1;
+ } catch (Dune::Exception &e) {
+ std::cerr << "Generic Dune error: " << e << std::endl;
+ return 2;
+ }
+ }
+ \endcode
+
+ \see exceptions.hh for detailed info
+
+ */
+
+ /*! \file
+ \brief A few common exception classes
+
+ This file defines a common framework for generating exception
+ subclasses and to throw them in a simple manner
+
+ */
+
+ /* forward declarations */
+ class Exception;
+ struct ExceptionHook;
+
+ /*! \class Exception
+ \brief Base class for Dune-Exceptions
+
+ all Dune exceptions are derived from this class via trivial subclassing:
+
+ \code
+ class MyException : public Dune::Exception {};
+ \endcode
+
+ You should not \c throw a Dune::Exception directly but use the macro
+ DUNE_THROW() instead which fills the message-buffer of the exception
+ in a standard way and features a way to pass the result in the
+ operator<<-style
+
+ \see DUNE_THROW, IOError, MathError
+
+ */
+ class Exception {
+ public:
+ Exception ();
+ void message(const std::string &msg); //!< store string in internal message buffer
+ const std::string& what() const; //!< output internal message buffer
+ static void registerHook (ExceptionHook * hook); //!< add a functor which is called before a Dune::Exception is emitted (see Dune::ExceptionHook) \see Dune::ExceptionHook
+ static void clearHook (); //!< remove all hooks
+ private:
+ std::string _message;
+ static ExceptionHook * _hook;
+ };
+
+ /*! \brief Base class to add a hook to the Dune::Exception
+
+ The user can add a functor which should be called before a Dune::Exception is emitted.
+
+
+ Example: attach a debugger to the process, if an exception is thrown
+ \code
+ struct ExceptionHookDebugger : public Dune::ExceptionHook
+ {
+ char * process_;
+ char * debugger_;
+ ExceptionHookDebugger (int argc, char ** argv, std::string debugger)
+ {
+ process_ = strdup(argv[0]);
+ debugger_ = strdup(debugger.c_str());
+ }
+ virtual void operator () ()
+ {
+ pid_t pid = getpid();
+ pid_t cpid;
+ cpid = fork();
+ if (cpid == 0) // child
+ {
+ char * argv[4];
+ argv[0] = debugger_;
+ argv[1] = process_;
+ argv[2] = new char[12];
+ snprintf(argv[2], 12, "%i", int(pid));
+ argv[3] = 0;
+ // execute debugger
+ std::cout << process_ << "\n";
+ std::cout << argv[0] << " "
+ << argv[1] << " "
+ << argv[2] << std::endl;
+ execv(argv[0], argv);
+ }
+ else // parent
+ {
+ // send application to sleep
+ kill(pid, SIGSTOP);
+ }
+ }
+ };
+ \endcode
+
+ This hook is registered via a static method of Dune::Exception:
+ \code
+ int main(int argc, char** argv) {
+ Dune::MPIHelper & mpihelper = Dune::MPIHelper::instance(argc,argv);
+ ExceptionHookDebugger debugger(argc, argv, "/usr/bin/ddd");
+ Dune::Exception::registerHook(& debugger);
+ try
+ {
+ ...
+ }
+ catch (std::string & s) {
+ std::cout << mpihelper.rank() << ": ERROR: " << s << std::endl;
+ }
+ catch (Dune::Exception & e) {
+ std::cout << mpihelper.rank() << ": DUNE ERROR: " << e.what() << std::endl;
+ }
+ }
+ \endcode
+
+ */
+ struct ExceptionHook
+ {
+ virtual ~ExceptionHook() {}
+ virtual void operator () () = 0;
+ };
+
+ /*
+ Implementation of Dune::Exception
+ */
+
+ inline Exception::Exception ()
+ {
+ // call the hook if necessary
+ if (_hook != 0) _hook->operator()();
+ }
+
+ inline void Exception::registerHook (ExceptionHook * hook)
+ {
+ _hook = hook;
+ }
+
+ inline void Exception::clearHook ()
+ {
+ _hook = 0;
+ }
+
+ inline void Exception::message(const std::string & msg)
+ {
+ _message = msg;
+ }
+
+ inline const std::string& Exception::what() const
+ {
+ return _message;
+ }
+
+ inline std::ostream& operator<<(std::ostream &stream, const Exception &e)
+ {
+ return stream << e.what();
+ }
+
+#ifndef DOXYGEN
+ // the "format" the exception-type gets printed. __FILE__ and
+ // __LINE__ are standard C-defines, the GNU cpp-infofile claims that
+ // C99 defines __func__ as well. __FUNCTION__ is a GNU-extension
+#define THROWSPEC(E) # E << " [" << __func__ << ":" << __FILE__ << ":" << __LINE__ << "]: "
+#endif // DOXYGEN
+
+ /*! Macro to throw an exception
+
+ \code
+ #include <dune/common/exceptions.hh>
+ \endcode
+
+ \param E exception class derived from Dune::Exception
+ \param m reason for this exception in ostream-notation
+
+ Example:
+
+ \code
+ if (filehandle == 0)
+ DUNE_THROW(FileError, "Could not open " << filename << " for reading!");
+ \endcode
+
+ DUNE_THROW automatically adds information about the exception thrown
+ to the text.
+
+ \note
+ you can add a hook to be called before a Dune::Exception is emitted,
+ e.g. to add additional information to the exception,
+ or to invoke a debugger during parallel debugging. (see Dune::ExceptionHook)
+
+ */
+ // this is the magic: use the usual do { ... } while (0) trick, create
+ // the full message via a string stream and throw the created object
+#define DUNE_THROW(E, m) do { E th__ex; std::ostringstream th__out; \
+ th__out << THROWSPEC(E) << m; th__ex.message(th__out.str()); throw th__ex; \
+} while (0)
+
+ /*! \brief Default exception class for I/O errors
+
+ This is a superclass for any errors dealing with file/socket I/O problems
+ like
+
+ - file not found
+ - could not write file
+ - could not connect to remote socket
+ */
+ class IOError : public Exception {};
+
+ /*! \brief Default exception class for mathematical errors
+
+ This is the superclass for all errors which are caused by
+ mathematical problems like
+
+ - matrix not invertible
+ - not convergent
+ */
+ class MathError : public Exception {};
+
+ /*! \brief Default exception class for range errors
+
+ This is the superclass for all errors which are caused because
+ the user tries to access data that was not allocated before.
+ These can be problems like
+
+ - accessing array entries behind the last entry
+ - adding the fourth non zero entry in a sparse matrix
+ with only three non zero entries per row
+
+ */
+ class RangeError : public Exception {};
+
+ /*! \brief Default exception for dummy implementations
+
+ This exception can be used for functions/methods
+
+ - that have to be implemented but should never be called
+ - that are missing
+ */
+ class NotImplemented : public Exception {};
+
+ /*! \brief Default exception class for OS errors
+
+ This class is thrown when a system-call is used and returns an
+ error.
+
+ */
+ class SystemError : public Exception {};
+
+ /*! \brief Default exception if memory allocation fails
+
+ */
+ class OutOfMemoryError : public SystemError {};
+
+ /*! \brief Default exception if a function was called while
+ the object is not in a valid state for that function.
+ */
+ class InvalidStateException : public Exception {};
+
+ /*! \brief Default exception if an error in the parallel
+ communication of the programm occured
+ \ingroup ParallelCommunication
+ */
+ class ParallelError : public Exception {};
+
+} // end namespace
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_ASSIGN_HH
+#define DUNE_ASSIGN_HH
+
+#include <dune/common/fvector.hh>
+#include <dune/common/fmatrix.hh>
+#include <dune/common/unused.hh>
+
+namespace Dune {
+
+ /**
+ * @file
+ * @brief Classes for implementing an assignment to FieldVector from a comma-separated list
+ */
+ /** @addtogroup Common
+ *
+ * @{
+ */
+
+ /**
+ * Emtpy namespace make this class and the object local to one object file
+ */
+ namespace {
+
+ /**
+ * @brief Initializer class for
+ *
+ * overload operator <<= for FieldVector assignment from Dune::Zero
+ */
+ struct Zero {
+ explicit Zero (int) {};
+ /** \brief Conversion operator to double */
+ operator double () { return 0.0; }
+ /** \brief Conversion operator to int */
+ operator int () { return 0; }
+ } zero(0);
+
+ /**
+ * @brief Marker class for next row
+ *
+ * overload operator <<= for FieldMatrix assignment
+ */
+ struct NextRow {
+ explicit NextRow (int) {};
+ } nextRow(0);
+ } // end empty namespace
+
+ /**
+ * @brief fvector assignment operator
+ *
+ * overload operator <<= for fvector assignment from Dune::Zero
+ *
+ * after including fassing.hh you can easily assign data to a FieldVector
+ * using
+ *
+ * @code
+ * FieldVector<double, 4> x; x <<= 1.0, 4.0, 10.0, 11.0;
+ * @endcode
+ *
+ * The operator checks that the whole vector is initalized.
+ * In case you know that all following entries will be zero padded, you can use
+ *
+ * @code
+ * FieldVector<double, 40> x; x <<= 1.0, 4.0, 10.0, 11.0, zero;
+ * @endcode
+ *
+ */
+ template <class T, int s>
+ class fvector_assigner
+ {
+ private:
+ FieldVector<T,s> & v;
+ int c;
+ bool temporary;
+ fvector_assigner();
+ public:
+ /*! @brief Copy Constructor */
+ fvector_assigner(fvector_assigner & a) : v(a.v), c(a.c), temporary(false)
+ {}
+ /*! @brief Constructor from vector and temporary flag
+ \param _v vector which should be initialized
+ \param t bool indicating, that this is a temporary object (see ~fvector_assigner)
+ */
+ fvector_assigner(FieldVector<T,s> & _v, bool t) : v(_v), c(0), temporary(t)
+ {};
+ /*! @brief Destructor
+ checks for complete initialization of the vector.
+ The check is skipped, if this object is marked temporary.
+ */
+ ~fvector_assigner()
+ {
+ if (!temporary && c!=s)
+ DUNE_THROW(MathError, "Trying to assign " << c <<
+ " entries to a FieldVector of size " << s);
+ }
+ /*! @brief append data to this vector */
+ fvector_assigner & append (const T & t)
+ {
+ v[c++] = t;
+ return *this;
+ }
+ /*! @brief append zeros to this vector
+ */
+ fvector_assigner & append (Zero z)
+ {
+ DUNE_UNUSED_PARAMETER(z);
+ while (c!=s) v[c++] = 0;
+ return *this;
+ }
+ /*! @brief append data to this vector
+ the overloaded comma operator is used to assign a comma separated list
+ of values to the vector
+ */
+ fvector_assigner & operator , (const T & t)
+ {
+ return append(t);
+ }
+ /*! @brief append zeros to this vector
+ the overloaded comma operator is used to stop the assign of values
+ to the vector, all remaining entries are assigned 0.
+ */
+ fvector_assigner & operator , (Zero z)
+ {
+ return append(z);
+ }
+ };
+
+ /**
+ * @brief fvector assignment operator
+ *
+ * overload operator <<= for fvector assignment
+ * from comma separated list of values
+ */
+ template <class T, class K, int s>
+ fvector_assigner<T,s> operator <<= (FieldVector<T,s> & v, const K & t)
+ {
+ return fvector_assigner<T,s>(v,true).append(t);
+ }
+
+ /**
+ * @brief fvector assignment operator
+ *
+ * overload operator <<= for fvector assignment from Dune::Zero
+ */
+ template <class T, int s>
+ fvector_assigner<T,s> operator <<= (FieldVector<T,s> & v, Zero z)
+ {
+ return fvector_assigner<T,s>(v,true).append(z);
+ }
+
+ /**
+ * @brief fmatrix assignment operator
+ *
+ * overload operator <<= for fmatrix assignment from Dune::Zero
+ *
+ * after including fassing.hh you can easily assign data to a FieldMatrix
+ * using
+ *
+ * @code
+ * FieldMatrix<double, 2,2> x; x <<= 1.0, 4.0, nextRow, 10.0, 11.0;
+ * @endcode
+ *
+ * The operator checks that the whole matrix is initalized.
+ * In case you know that all following entries of a row will be zero padded, you can use
+ *
+ * @code
+ * FieldMatrix<double, 4, 4> x; x <<= 1.0, zero, nextRow, 10.0, 11.0;
+ * @endcode
+ *
+ */
+ template <class T, int n, int m>
+ class fmatrix_assigner
+ {
+ private:
+ FieldMatrix<T,n,m> & A;
+ int c;
+ int r;
+ bool temporary;
+ bool thrown;
+
+ void end_row()
+ {
+ if (!temporary && c!=m && !thrown) {
+ thrown=true;
+ DUNE_THROW(MathError, "Trying to assign " << c <<
+ " entries to a FieldMatrix row of size " << m);
+ }
+ c=0;
+ }
+ public:
+ /*! @brief Copy Constructor */
+ fmatrix_assigner(fmatrix_assigner & a) : A(a.A), c(a.c), r(a.r), temporary(false), thrown(a.thrown)
+ {}
+ /*! @brief Constructor from matrix and temporary flag
+ \param _A matrix which should be initialized
+ \param t bool indicating, that this is a temporary object (see ~fmatrix_assigner)
+ */
+ fmatrix_assigner(FieldMatrix<T,n,m> & _A, bool t) : A(_A), c(0), r(0), temporary(t),
+ thrown(false)
+ {};
+ /*! @brief Destructor
+ checks for complete initialization of the matrix.
+ The check is skipped, if this object is marked temporary.
+ */
+ ~fmatrix_assigner()
+ {
+ end_row();
+ if (!temporary && r!=n-1 && !thrown) {
+ thrown=true;
+ DUNE_THROW(MathError, "Trying to assign " << r <<
+ " rows to a FieldMatrix of size " << n << " x " << m);
+ }
+ }
+ /*! @brief append data to this matrix */
+ fmatrix_assigner & append (const T & t)
+ {
+ // Check whether we have passed the last row
+ if(r>=m) {
+ thrown=true;
+ DUNE_THROW(MathError, "Trying to assign more than " << m <<
+ " rows to a FieldMatrix of size " << n << " x " << m);
+ }
+ A[r][c++] = t;
+ return *this;
+ }
+ /*! @brief append zeros to this matrix
+ */
+ fmatrix_assigner & append (Zero z)
+ {
+ DUNE_UNUSED_PARAMETER(z);
+ while (c!=m) A[r][c++] = 0;
+ return *this;
+ }
+ /*! @brief move to next row of the matrix
+ */
+ fmatrix_assigner & append (NextRow nr)
+ {
+ DUNE_UNUSED_PARAMETER(nr);
+ end_row();
+ r++;
+ return *this;
+ }
+ /*! @brief append data to this matrix
+ the overloaded comma operator is used to assign a comma separated list
+ of values to the matrix
+ */
+ fmatrix_assigner & operator , (const T & t)
+ {
+ return append(t);
+ }
+ /*! @brief append zeros to this matrix
+ the overloaded comma operator is used to stop the assign of values
+ to the matrix, all remaining entries are assigned 0.
+ */
+ fmatrix_assigner & operator , (Zero z)
+ {
+ return append(z);
+ }
+ /*! @brief append zeros to this matrix
+ the overloaded comma operator is used to stop the assign of values
+ to the current row, it will be checked whether all entries have been
+ assigned values.
+ */
+ fmatrix_assigner & operator , (NextRow nr)
+ {
+ return append(nr);
+ }
+ };
+
+ /**
+ * @brief FieldMatrix assignment operator
+ *
+ * overload operator <<= for FieldMatrix assignment
+ * from comma separated list of values
+ */
+ template <class T, class K, int n, int m>
+ fmatrix_assigner<T,n,m> operator <<= (FieldMatrix<T,n,m> & v, const K & t)
+ {
+ return fmatrix_assigner<T,n,m>(v,true).append(t);
+ }
+
+ /**
+ * @brief FieldMatrix assignment operator
+ *
+ * overload operator <<= for FieldMatrix row assignment from Dune::Zero
+ */
+ template <class T, int n, int m>
+ fmatrix_assigner<T,n,m> operator <<= (FieldMatrix<T,n,m> & v, Zero z)
+ {
+ return fmatrix_assigner<T,n,m>(v,true).append(z);
+ }
+
+} // end namespace Dune
+
+#endif // DUNE_ASSIGN_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#include "float_cmp.hh"
+
+#include <vector>
+#include <limits>
+#include <algorithm>
+#include <cstdlib>
+#include <dune/common/fvector.hh>
+
+namespace Dune {
+
+
+ namespace FloatCmp {
+ // traits
+ //! Mapping of value type to epsilon type
+ /**
+ * @ingroup FloatCmp
+ * @tparam T The value type
+ */
+ template<class T> struct EpsilonType {
+ //! The epsilon type corresponding to value type T
+ typedef T Type;
+ };
+ //! Specialization of EpsilonType for std::vector
+ /**
+ * @ingroup FloatCmp
+ * @tparam T The value_type of the std::vector
+ * @tparam A The Allocator of the std::vector
+ */
+ template<class T, typename A>
+ struct EpsilonType<std::vector<T, A> > {
+ //! The epsilon type corresponding to value type std::vector<T, A>
+ typedef EpsilonType<T> Type;
+ };
+ //! Specialization of EpsilonType for Dune::FieldVector
+ /**
+ * @ingroup FloatCmp
+ * @tparam T The field_type of the Dune::FieldVector
+ * @tparam n The size of the Dune::FieldVector
+ */
+ template<class T, int n>
+ struct EpsilonType<FieldVector<T, n> > {
+ //! The epsilon type corresponding to value type Dune::FieldVector<T, n>
+ typedef EpsilonType<T> Type;
+ };
+
+ // default epsilon
+ template<class T>
+ struct DefaultEpsilon<T, relativeWeak> {
+ static typename EpsilonType<T>::Type value()
+ { return std::numeric_limits<typename EpsilonType<T>::Type>::epsilon()*8; }
+ };
+ template<class T>
+ struct DefaultEpsilon<T, relativeStrong> {
+ static typename EpsilonType<T>::Type value()
+ { return std::numeric_limits<typename EpsilonType<T>::Type>::epsilon()*8; }
+ };
+ template<class T>
+ struct DefaultEpsilon<T, absolute> {
+ static typename EpsilonType<T>::Type value()
+ { return std::max(std::numeric_limits<typename EpsilonType<T>::Type>::epsilon(), 1e-6); }
+ };
+
+ namespace Detail {
+ // basic comparison
+ template<class T, CmpStyle style = defaultCmpStyle>
+ struct eq_t;
+ template<class T>
+ struct eq_t<T, relativeWeak> {
+ static bool eq(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T>::value())
+ { return std::abs(first - second) <= epsilon*std::max(std::abs(first), std::abs(second)); }
+ };
+ template<class T>
+ struct eq_t<T, relativeStrong> {
+ static bool eq(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T>::value())
+ { return std::abs(first - second) <= epsilon*std::min(std::abs(first), std::abs(second)); }
+ };
+ template<class T>
+ struct eq_t<T, absolute> {
+ static bool eq(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T>::value())
+ { return std::abs(first-second) <= epsilon; }
+ };
+ template<class T, CmpStyle cstyle>
+ struct eq_t<std::vector<T>, cstyle> {
+ static bool eq(const std::vector<T> &first,
+ const std::vector<T> &second,
+ typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T>::value()) {
+ unsigned int size = first.size();
+ if(size != second.size()) return false;
+ for(unsigned int i = 0; i < size; ++i)
+ if(!eq_t<T, cstyle>(first[i], second[i], epsilon))
+ return false;
+ return true;
+ }
+ };
+ template<class T, int n, CmpStyle cstyle>
+ struct eq_t<Dune::FieldVector<T, n>, cstyle> {
+ static bool eq(const Dune::FieldVector<T, n> &first,
+ const Dune::FieldVector<T, n> &second,
+ typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T>::value()) {
+ for(int i = 0; i < n; ++i)
+ if(!eq_t<T, cstyle>(first[i], second[i], epsilon))
+ return false;
+ return true;
+ }
+ };
+ } // namespace Detail
+
+ // operations in functional style
+ template <class T, CmpStyle style>
+ bool eq(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon)
+ {
+ return Detail::eq_t<T, style>::eq(first, second, epsilon);
+ }
+ template <class T, CmpStyle style>
+ bool ne(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon)
+ {
+ return !eq<T, style>(first, second, epsilon);
+ }
+ template <class T, CmpStyle style>
+ bool gt(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon)
+ {
+ return first > second && ne<T, style>(first, second, epsilon);
+ }
+ template <class T, CmpStyle style>
+ bool lt(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon)
+ {
+ return first < second && ne<T, style>(first, second, epsilon);
+ }
+ template <class T, CmpStyle style>
+ bool ge(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon)
+ {
+ return first > second || eq<T, style>(first, second, epsilon);
+ }
+ template <class T, CmpStyle style>
+ bool le(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon)
+ {
+ return first < second || eq<T, style>(first, second, epsilon);
+ }
+
+ // default template arguments
+ template <class T>
+ bool eq(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T, defaultCmpStyle>::value())
+ {
+ return eq<T, defaultCmpStyle>(first, second, epsilon);
+ }
+ template <class T>
+ bool ne(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T, defaultCmpStyle>::value())
+ {
+ return ne<T, defaultCmpStyle>(first, second, epsilon);
+ }
+ template <class T>
+ bool gt(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T, defaultCmpStyle>::value())
+ {
+ return gt<T, defaultCmpStyle>(first, second, epsilon);
+ }
+ template <class T>
+ bool lt(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T, defaultCmpStyle>::value())
+ {
+ return lt<T, defaultCmpStyle>(first, second, epsilon);
+ }
+ template <class T>
+ bool ge(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T, defaultCmpStyle>::value())
+ {
+ return ge<T, defaultCmpStyle>(first, second, epsilon);
+ }
+ template <class T>
+ bool le(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T, defaultCmpStyle>::value())
+ {
+ return le<T, defaultCmpStyle>(first, second, epsilon);
+ }
+
+ // rounding operations
+ namespace Detail {
+ template<class I, class T, CmpStyle cstyle = defaultCmpStyle, RoundingStyle rstyle = defaultRoundingStyle>
+ struct round_t;
+ template<class I, class T, CmpStyle cstyle>
+ struct round_t<I, T, cstyle, downward> {
+ static I
+ round(const T &val,
+ typename EpsilonType<T>::Type epsilon = (DefaultEpsilon<T, cstyle>::value())) {
+ // first get an approximation
+ I lower = I(val);
+ I upper;
+ if(eq<T, cstyle>(T(lower), val, epsilon)) return lower;
+ if(T(lower) > val) { upper = lower; lower--; }
+ else upper = lower+1;
+ if(le<T, cstyle>(val - T(lower), T(upper) - val, epsilon))
+ return lower;
+ else return upper;
+ }
+ };
+ template<class I, class T, CmpStyle cstyle>
+ struct round_t<I, T, cstyle, upward> {
+ static I
+ round(const T &val,
+ typename EpsilonType<T>::Type epsilon = (DefaultEpsilon<T, cstyle>::value())) {
+ // first get an approximation
+ I lower = I(val);
+ I upper;
+ if(eq<T, cstyle>(T(lower), val, epsilon)) return lower;
+ if(T(lower) > val) { upper = lower; lower--; }
+ else upper = lower+1;
+ if(lt<T, cstyle>(val - T(lower), T(upper) - val, epsilon))
+ return lower;
+ else return upper;
+ }
+ };
+ template<class I, class T, CmpStyle cstyle>
+ struct round_t<I, T, cstyle, towardZero> {
+ static I
+ round(const T &val,
+ typename EpsilonType<T>::Type epsilon = (DefaultEpsilon<T, cstyle>::value())) {
+ if(val > T(0))
+ return round_t<I, T, cstyle, downward>::round(val, epsilon);
+ else return round_t<I, T, cstyle, upward>::round(val, epsilon);
+ }
+ };
+ template<class I, class T, CmpStyle cstyle>
+ struct round_t<I, T, cstyle, towardInf> {
+ static I
+ round(const T &val,
+ typename EpsilonType<T>::Type epsilon = (DefaultEpsilon<T, cstyle>::value())) {
+ if(val > T(0))
+ return round_t<I, T, cstyle, upward>::round(val, epsilon);
+ else return round_t<I, T, cstyle, downward>::round(val, epsilon);
+ }
+ };
+ template<class I, class T, CmpStyle cstyle, RoundingStyle rstyle>
+ struct round_t<std::vector<I>, std::vector<T>, cstyle, rstyle> {
+ static std::vector<I>
+ round(const T &val,
+ typename EpsilonType<T>::Type epsilon = (DefaultEpsilon<T, cstyle>::value())) {
+ unsigned int size = val.size();
+ std::vector<I> res(size);
+ for(unsigned int i = 0; i < size; ++i)
+ res[i] = round_t<I, T, cstyle, rstyle>::round(val[i], epsilon);
+ return res;
+ }
+ };
+ template<class I, class T, int n, CmpStyle cstyle, RoundingStyle rstyle>
+ struct round_t<Dune::FieldVector<I, n>, Dune::FieldVector<T, n>, cstyle, rstyle> {
+ static Dune::FieldVector<I, n>
+ round(const T &val,
+ typename EpsilonType<T>::Type epsilon = (DefaultEpsilon<T, cstyle>::value())) {
+ Dune::FieldVector<I, n> res;
+ for(int i = 0; i < n; ++i)
+ res[i] = round_t<I, T, cstyle, rstyle>::round(val[i], epsilon);
+ return res;
+ }
+ };
+ } // namespace Detail
+ template<class I, class T, CmpStyle cstyle, RoundingStyle rstyle>
+ I round(const T &val, typename EpsilonType<T>::Type epsilon /*= DefaultEpsilon<T, cstyle>::value()*/)
+ {
+ return Detail::round_t<I, T, cstyle, rstyle>::round(val, epsilon);
+ }
+ template<class I, class T, CmpStyle cstyle>
+ I round(const T &val, typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T, cstyle>::value())
+ {
+ return round<I, T, cstyle, defaultRoundingStyle>(val, epsilon);
+ }
+ template<class I, class T, RoundingStyle rstyle>
+ I round(const T &val, typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T, defaultCmpStyle>::value())
+ {
+ return round<I, T, defaultCmpStyle, rstyle>(val, epsilon);
+ }
+ template<class I, class T>
+ I round(const T &val, typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T, defaultCmpStyle>::value())
+ {
+ return round<I, T, defaultCmpStyle>(val, epsilon);
+ }
+
+ // truncation
+ namespace Detail {
+ template<class I, class T, CmpStyle cstyle = defaultCmpStyle, RoundingStyle rstyle = defaultRoundingStyle>
+ struct trunc_t;
+ template<class I, class T, CmpStyle cstyle>
+ struct trunc_t<I, T, cstyle, downward> {
+ static I
+ trunc(const T &val,
+ typename EpsilonType<T>::Type epsilon = (DefaultEpsilon<T, cstyle>::value())) {
+ // this sould be optimized away unless needed
+ if(!std::numeric_limits<I>::is_signed)
+ // make sure this works for all useful cases even if I is an unsigned type
+ if(eq<T, cstyle>(val, T(0), epsilon)) return I(0);
+ // first get an approximation
+ I lower = I(val); // now |val-lower| < 1
+ // make sure we're really lower in case the cast truncated to an unexpected direction
+ if(T(lower) > val) lower--; // now val-lower < 1
+ // check whether lower + 1 is approximately val
+ if(eq<T, cstyle>(T(lower+1), val, epsilon))
+ return lower+1;
+ else return lower;
+ }
+ };
+ template<class I, class T, CmpStyle cstyle>
+ struct trunc_t<I, T, cstyle, upward> {
+ static I
+ trunc(const T &val,
+ typename EpsilonType<T>::Type epsilon = (DefaultEpsilon<T, cstyle>::value())) {
+ I upper = trunc_t<I, T, cstyle, downward>::trunc(val, epsilon);
+ if(ne<T, cstyle>(T(upper), val, epsilon)) ++upper;
+ return upper;
+ }
+ };
+ template<class I, class T, CmpStyle cstyle>
+ struct trunc_t<I, T, cstyle, towardZero> {
+ static I
+ trunc(const T &val,
+ typename EpsilonType<T>::Type epsilon = (DefaultEpsilon<T, cstyle>::value())) {
+ if(val > T(0)) return trunc_t<I, T, cstyle, downward>::trunc(val, epsilon);
+ else return trunc_t<I, T, cstyle, upward>::trunc(val, epsilon);
+ }
+ };
+ template<class I, class T, CmpStyle cstyle>
+ struct trunc_t<I, T, cstyle, towardInf> {
+ static I
+ trunc(const T &val,
+ typename EpsilonType<T>::Type epsilon = (DefaultEpsilon<T, cstyle>::value())) {
+ if(val > T(0)) return trunc_t<I, T, cstyle, upward>::trunc(val, epsilon);
+ else return trunc_t<I, T, cstyle, downward>::trunc(val, epsilon);
+ }
+ };
+ template<class I, class T, CmpStyle cstyle, RoundingStyle rstyle>
+ struct trunc_t<std::vector<I>, std::vector<T>, cstyle, rstyle> {
+ static std::vector<I>
+ trunc(const std::vector<T> &val,
+ typename EpsilonType<T>::Type epsilon = (DefaultEpsilon<T, cstyle>::value())) {
+ unsigned int size = val.size();
+ std::vector<I> res(size);
+ for(unsigned int i = 0; i < size; ++i)
+ res[i] = trunc_t<I, T, cstyle, rstyle>::trunc(val[i], epsilon);
+ return res;
+ }
+ };
+ template<class I, class T, int n, CmpStyle cstyle, RoundingStyle rstyle>
+ struct trunc_t<Dune::FieldVector<I, n>, Dune::FieldVector<T, n>, cstyle, rstyle> {
+ static Dune::FieldVector<I, n>
+ trunc(const Dune::FieldVector<T, n> &val,
+ typename EpsilonType<T>::Type epsilon = (DefaultEpsilon<T, cstyle>::value())) {
+ Dune::FieldVector<I, n> res;
+ for(int i = 0; i < n; ++i)
+ res[i] = trunc_t<I, T, cstyle, rstyle>::trunc(val[i], epsilon);
+ return res;
+ }
+ };
+ } // namespace Detail
+ template<class I, class T, CmpStyle cstyle, RoundingStyle rstyle>
+ I trunc(const T &val, typename EpsilonType<T>::Type epsilon /*= DefaultEpsilon<T, cstyle>::value()*/)
+ {
+ return Detail::trunc_t<I, T, cstyle, rstyle>::trunc(val, epsilon);
+ }
+ template<class I, class T, CmpStyle cstyle>
+ I trunc(const T &val, typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T, cstyle>::value())
+ {
+ return trunc<I, T, cstyle, defaultRoundingStyle>(val, epsilon);
+ }
+ template<class I, class T, RoundingStyle rstyle>
+ I trunc(const T &val, typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T, defaultCmpStyle>::value())
+ {
+ return trunc<I, T, defaultCmpStyle, rstyle>(val, epsilon);
+ }
+ template<class I, class T>
+ I trunc(const T &val, typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T, defaultCmpStyle>::value())
+ {
+ return trunc<I, T, defaultCmpStyle>(val, epsilon);
+ }
+ } //namespace Dune
+
+ // oo interface
+ template<class T, FloatCmp::CmpStyle cstyle_, FloatCmp::RoundingStyle rstyle_>
+ FloatCmpOps<T, cstyle_, rstyle_>::
+ FloatCmpOps(EpsilonType epsilon) : epsilon_(epsilon) {}
+
+
+ template<class T, FloatCmp::CmpStyle cstyle_, FloatCmp::RoundingStyle rstyle_>
+ typename FloatCmpOps<T, cstyle_, rstyle_>::EpsilonType
+ FloatCmpOps<T, cstyle_, rstyle_>::epsilon() const
+ {
+ return epsilon_;
+ }
+
+ template<class T, FloatCmp::CmpStyle cstyle_, FloatCmp::RoundingStyle rstyle_>
+ void
+ FloatCmpOps<T, cstyle_, rstyle_>::epsilon(EpsilonType epsilon__)
+ {
+ epsilon_ = epsilon__;
+ }
+
+
+ template<class T, FloatCmp::CmpStyle cstyle_, FloatCmp::RoundingStyle rstyle_>
+ bool FloatCmpOps<T, cstyle_, rstyle_>::
+ eq(const ValueType &first, const ValueType &second) const
+ {
+ return Dune::FloatCmp::eq<ValueType, cstyle>(first, second, epsilon_);
+ }
+
+ template<class T, FloatCmp::CmpStyle cstyle_, FloatCmp::RoundingStyle rstyle_>
+ bool FloatCmpOps<T, cstyle_, rstyle_>::
+ ne(const ValueType &first, const ValueType &second) const
+ {
+ return Dune::FloatCmp::ne<ValueType, cstyle>(first, second, epsilon_);
+ }
+
+ template<class T, FloatCmp::CmpStyle cstyle_, FloatCmp::RoundingStyle rstyle_>
+ bool FloatCmpOps<T, cstyle_, rstyle_>::
+ gt(const ValueType &first, const ValueType &second) const
+ {
+ return Dune::FloatCmp::gt<ValueType, cstyle>(first, second, epsilon_);
+ }
+
+ template<class T, FloatCmp::CmpStyle cstyle_, FloatCmp::RoundingStyle rstyle_>
+ bool FloatCmpOps<T, cstyle_, rstyle_>::
+ lt(const ValueType &first, const ValueType &second) const
+ {
+ return Dune::FloatCmp::lt<ValueType, cstyle>(first, second, epsilon_);
+ }
+
+ template<class T, FloatCmp::CmpStyle cstyle_, FloatCmp::RoundingStyle rstyle_>
+ bool FloatCmpOps<T, cstyle_, rstyle_>::
+ ge(const ValueType &first, const ValueType &second) const
+ {
+ return Dune::FloatCmp::ge<ValueType, cstyle>(first, second, epsilon_);
+ }
+
+ template<class T, FloatCmp::CmpStyle cstyle_, FloatCmp::RoundingStyle rstyle_>
+ bool FloatCmpOps<T, cstyle_, rstyle_>::
+ le(const ValueType &first, const ValueType &second) const
+ {
+ return Dune::FloatCmp::le<ValueType, cstyle>(first, second, epsilon_);
+ }
+
+
+ template<class T, FloatCmp::CmpStyle cstyle_, FloatCmp::RoundingStyle rstyle_>
+ template<class I>
+ I FloatCmpOps<T, cstyle_, rstyle_>::
+ round(const ValueType &val) const
+ {
+ return Dune::FloatCmp::round<I, ValueType, cstyle, rstyle_>(val, epsilon_);
+ }
+
+ template<class T, FloatCmp::CmpStyle cstyle_, FloatCmp::RoundingStyle rstyle_>
+ template<class I>
+ I FloatCmpOps<T, cstyle_, rstyle_>::
+ trunc(const ValueType &val) const
+ {
+ return Dune::FloatCmp::trunc<I, ValueType, cstyle, rstyle_>(val, epsilon_);
+ }
+
+} //namespace Dune
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_COMMON_FLOAT_CMP_HH
+#define DUNE_COMMON_FLOAT_CMP_HH
+
+/** \file
+ * \brief Various ways to compare floating-point numbers
+ */
+
+/**
+ @addtogroup FloatCmp FloatCmp
+ @ingroup Common
+
+ @section How_to_compare How to compare floats
+
+ When comparing floating point numbers for equality, one often faces the
+ problem that floating point operations are not always exact. For example on
+ i386 the expression
+ @code
+ 0.2 + 0.2 + 0.2 + 0.2 + 0.2 + 0.2 + 0.2 + 0.2 + 0.2 + 0.2 == 2.0
+ @endcode
+ evaluates to
+ @code
+ 1.99999999999999977796 == 2.00000000000000000000
+ @endcode
+ which is false. One solution is to compare approximately, using an epsilon
+ which says how much deviation to accept.
+
+ The most straightforward way of comparing is using an @em absolute epsilon.
+ This means comparison for equality is replaced by
+ @code
+ abs(first-second) <= epsilon
+ @endcode
+ This has a severe disadvantage: if you have an epsilon like 1e-10 but first
+ and second are of the magnitude 1e-15 everything will compare equal which is
+ certainly not what you want. This can be overcome by selecting an
+ appropriate epsilon. Nevertheless this method of comparing is not
+ recommended in general, and we will present a more robus method in the
+ next paragraph.
+
+ There is another way of comparing approximately, using a @em relative
+ epsilon which is then scaled with first:
+ @code
+ abs(first-second) <= epsilon * abs(first)
+ @endcode
+ Of cource the comparison should be symmetric in first and second so we
+ cannot arbitrarily select either first or second to scale epsilon. The are
+ two symmetric variants, @em relative_weak
+ @code
+ abs(first-second) <= epsilon * max(abs(first), abs(second))
+ @endcode
+ and @em relative_strong
+ @code
+ abs(first-second) <= epsilon * min(abs(first), abs(second))
+ @endcode
+ Both variants are good, but in practice the relative_weak variant is
+ preferred. This is also the default variant.
+
+ \note Although using a relative epsilon is better than using an absolute
+ epsilon, using a relative epsilon leads to problems if either first or
+ second equals 0. In principle the relative method can be combined
+ with an absolute method using an epsilon near the minimum
+ representable positive value, but this is not implemented here.
+
+ There is a completely different way of comparing floats. Instead of giving
+ an epsilon, the programmer states how many representable value are allowed
+ between first and second. See the "Comparing using integers" section in
+ http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
+ for more about that.
+
+ @section Interface Interface
+
+ To do the comparison, you can use the free functions @link
+ Dune::FloatCmp::eq eq()@endlink, @link Dune::FloatCmp::ne ne()@endlink,
+ @link Dune::FloatCmp::gt gt()@endlink, @link Dune::FloatCmp::lt
+ lt()@endlink, @link Dune::FloatCmp::ge ge()@endlink and @link
+ Dune::FloatCmp::le le()@endlink from the namespace Dune::FloatCmp. They
+ take the values to compare and optionally an epsilon, which defaults to 8
+ times the machine epsilon (the difference between 1.0 and the smallest
+ representable value > 1.0) for relative comparisons, or simply 1e-6 for
+ absolute comparisons. The compare style can be given as an optional second
+ template parameter and defaults to relative_weak.
+
+ You can also use the class Dune::FloatCmpOps which has @link
+ Dune::FloatCmpOps::eq eq()@endlink, @link Dune::FloatCmpOps::ne
+ ne()@endlink, @link Dune::FloatCmpOps::gt gt()@endlink, @link
+ Dune::FloatCmpOps::lt lt()@endlink, @link Dune::FloatCmpOps::ge ge()@endlink
+ and @link Dune::FloatCmpOps::le le()@endlink as member functions. In this
+ case the class encapsulates the epsilon and the comparison style (again the
+ defaults from the previous paragraph apply). This may be more convenient if
+ you write your own class utilizing floating point comparisons, and you want
+ the user of you class to specify epsilon and compare style.
+ */
+
+//! Dune namespace
+namespace Dune {
+ //! FloatCmp namespace
+ //! @ingroup FloatCmp
+ namespace FloatCmp {
+ // basic constants
+ //! How to compare
+ //! @ingroup FloatCmp
+ enum CmpStyle {
+ //! |a-b|/|a| <= epsilon || |a-b|/|b| <= epsilon
+ relativeWeak,
+ //! |a-b|/|a| <= epsilon && |a-b|/|b| <= epsilon
+ relativeStrong,
+ //! |a-b| <= epsilon
+ absolute,
+ //! the global default compare style (relative_weak)
+ defaultCmpStyle = relativeWeak
+ };
+ //! How to round or truncate
+ //! @ingroup FloatCmp
+ enum RoundingStyle {
+ //! always round toward 0
+ towardZero,
+ //! always round away from 0
+ towardInf,
+ //! round toward \f$-\infty\f$
+ downward,
+ //! round toward \f$+\infty\f$
+ upward,
+ //! the global default rounding style (toward_zero)
+ defaultRoundingStyle = towardZero
+ };
+
+ template<class T> struct EpsilonType;
+
+ //! mapping from a value type and a compare style to a default epsilon
+ /**
+ * @ingroup FloatCmp
+ * @tparam T The value type to map from
+ * @tparam style The compare style to map from
+ */
+ template<class T, CmpStyle style = defaultCmpStyle>
+ struct DefaultEpsilon {
+ //! Returns the default epsilon for the given value type and compare style
+ static typename EpsilonType<T>::Type value();
+ };
+
+ // operations in functional style
+
+ //! @addtogroup FloatCmp
+ //! @{
+
+ //! test for equality using epsilon
+ /**
+ * @tparam T Type of the values to compare
+ * @tparam style How to compare. This defaults to defaultCmpStyle.
+ * @param first left operand of equals operation
+ * @param second right operand of equals operation
+ * @param epsilon The epsilon to use in the comparison
+ */
+ template <class T, CmpStyle style /*= defaultCmpStyle*/>
+ bool eq(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T, style>::value());
+ //! test for inequality using epsilon
+ /**
+ * @tparam T Type of the values to compare
+ * @tparam style How to compare. This defaults to defaultCmpStyle.
+ * @param first left operand of not-equal operation
+ * @param second right operand of not-equal operation
+ * @param epsilon The epsilon to use in the comparison
+ * @return !eq(first, second, epsilon)
+ */
+ template <class T, CmpStyle style /*= defaultCmpStyle*/>
+ bool ne(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T, style>::value());
+ //! test if first greater than second
+ /**
+ * @tparam T Type of the values to compare
+ * @tparam style How to compare. This defaults to defaultCmpStyle.
+ * @param first left operand of greater-than operation
+ * @param second right operand of greater-than operation
+ * @param epsilon The epsilon to use in the comparison
+ * @return ne(first, second, epsilon) && first > second
+ *
+ * this is like first > second but the region that compares equal with an
+ * epsilon is excluded
+ */
+ template <class T, CmpStyle style /*= defaultCmpStyle*/>
+ bool gt(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T, style>::value());
+ //! test if first lesser than second
+ /**
+ * @tparam T Type of the values to compare
+ * @tparam style How to compare. This defaults to defaultCmpStyle.
+ * @param first left operand of less-than operation
+ * @param second right operand of less-than operation
+ * @param epsilon The epsilon to use in the comparison
+ * @return ne(first, second, epsilon) && first < second
+ *
+ * this is like first < second, but the region that compares equal with an
+ * epsilon is excluded
+ */
+ template <class T, CmpStyle style /*= defaultCmpStyle*/>
+ bool lt(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T, style>::value());
+ //! test if first greater or equal second
+ /**
+ * @tparam T Type of the values to compare
+ * @tparam style How to compare. This defaults to defaultCmpStyle.
+ * @param first left operand of greater-or-equals operation
+ * @param second right operand of greater-or-equals operation
+ * @param epsilon The epsilon to use in the comparison
+ * @return eq(first, second, epsilon) || first > second
+ *
+ * this is like first > second, but the region that compares equal with an
+ * epsilon is also included
+ */
+ template <class T, CmpStyle style /*= defaultCmpStyle*/>
+ bool ge(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T, style>::value());
+ //! test if first lesser or equal second
+ /**
+ * @tparam T Type of the values to compare
+ * @tparam style How to compare. This defaults to defaultCmpStyle.
+ * @param first left operand of less-or-equals operation
+ * @param second right operand of less-or-equals operation
+ * @param epsilon The epsilon to use in the comparison
+ * @return eq(first, second) || first > second
+ *
+ * this is like first > second, but the region that compares equal with an
+ * epsilon is also included
+ */
+ template <class T, CmpStyle style /*= defaultCmpStyle*/>
+ bool le(const T &first,
+ const T &second,
+ typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T, style>::value());
+
+ // rounding operations
+ //! round using epsilon
+ /**
+ * @tparam I The integral type to round to
+ * @tparam T Type of the value to round
+ * @tparam cstyle How to compare. This defaults to defaultCmpStyle.
+ * @tparam rstyle How to round. This defaults to defaultRoundingStyle.
+ * @param val The value to round
+ * @param epsilon The epsilon to use in comparisons
+ * @return The rounded value
+ *
+ * Round according to rstyle. If val is already near the mean of two
+ * adjacent integers in terms of epsilon, the result will be the rounded
+ * mean.
+ */
+ template<class I, class T, CmpStyle cstyle /*= defaultCmpStyle*/, RoundingStyle rstyle /*= defaultRoundingStyle*/>
+ I round(const T &val, typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T, cstyle>::value());
+ // truncation
+ //! truncate using epsilon
+ /**
+ * @tparam I The integral type to truncate to
+ * @tparam T Type of the value to truncate
+ * @tparam cstyle How to compare. This defaults to defaultCmpStyle.
+ * @tparam rstyle How to truncate. This defaults to defaultRoundingStyle.
+ * @param val The value to truncate
+ * @param epsilon The epsilon to use in comparisons
+ * @return The truncated value
+ *
+ * Truncate according to rstyle. If val is already near an integer in
+ * terms of epsilon, the result will be that integer instead of the real
+ * truncated value.
+ */
+ template<class I, class T, CmpStyle cstyle /*= defaultCmpStyle*/, RoundingStyle rstyle /*= defaultRoundingStyle*/>
+ I trunc(const T &val, typename EpsilonType<T>::Type epsilon = DefaultEpsilon<T, cstyle>::value());
+
+ //! @}
+ // group FloatCmp
+ } //namespace FloatCmp
+
+
+ // oo interface
+ //! Class encapsulating a default epsilon
+ /**
+ * @ingroup FloatCmp
+ * @tparam T Type of the values to compare
+ * @tparam cstyle_ How to compare
+ * @tparam rstyle_ How to round
+ */
+ template<class T, FloatCmp::CmpStyle cstyle_ = FloatCmp::defaultCmpStyle,
+ FloatCmp::RoundingStyle rstyle_ = FloatCmp::defaultRoundingStyle>
+ class FloatCmpOps {
+ typedef FloatCmp::CmpStyle CmpStyle;
+ typedef FloatCmp::RoundingStyle RoundingStyle;
+
+ public:
+ // record template parameters
+ //! How comparisons are done
+ static const CmpStyle cstyle = cstyle_;
+ //! How rounding is done
+ static const RoundingStyle rstyle = rstyle_;
+ //! Type of the values to compare
+ typedef T ValueType;
+ //! Type of the epsilon.
+ /**
+ * May be different from the value type, for example for complex<double>
+ */
+ typedef typename FloatCmp::EpsilonType<T>::Type EpsilonType;
+
+ private:
+ EpsilonType epsilon_;
+
+ typedef FloatCmp::DefaultEpsilon<EpsilonType, cstyle> DefaultEpsilon;
+
+ public:
+ //! construct an operations object
+ /**
+ * @param epsilon Use the specified epsilon for comparing
+ */
+ FloatCmpOps(EpsilonType epsilon = DefaultEpsilon::value());
+
+ //! return the current epsilon
+ EpsilonType epsilon() const;
+ //! set new epsilon
+ void epsilon(EpsilonType epsilon__);
+
+ //! test for equality using epsilon
+ bool eq(const ValueType &first, const ValueType &second) const;
+ //! test for inequality using epsilon
+ /**
+ * this is exactly !eq(first, second)
+ */
+ bool ne(const ValueType &first, const ValueType &second) const;
+ //! test if first greater than second
+ /**
+ * this is exactly ne(first, second) && first > second, i.e. greater but
+ * the region that compares equal with an epsilon is excluded
+ */
+ bool gt(const ValueType &first, const ValueType &second) const;
+ //! test if first lesser than second
+ /**
+ * this is exactly ne(first, second) && first < second, i.e. lesser but
+ * the region that compares equal with an epsilon is excluded
+ */
+ bool lt(const ValueType &first, const ValueType &second) const;
+ //! test if first greater or equal second
+ /**
+ * this is exactly eq(first, second) || first > second, i.e. greater but
+ * the region that compares equal with an epsilon is also included
+ */
+ bool ge(const ValueType &first, const ValueType &second) const;
+ //! test if first lesser or equal second
+ /**
+ * this is exactly eq(first, second) || first > second, i.e. lesser but
+ * the region that compares equal with an epsilon is also included
+ */
+ bool le(const ValueType &first, const ValueType &second) const;
+
+ //! round using epsilon
+ /**
+ * @tparam I The integral type to round to
+ *
+ * @param val The value to round
+ *
+ * Round according to rstyle. If val is already near the mean of two
+ * adjacent integers in terms of epsilon, the result will be the rounded
+ * mean.
+ */
+ template<class I>
+ I round(const ValueType &val) const;
+
+ //! truncate using epsilon
+ /**
+ * @tparam I The integral type to truncate to
+ *
+ * @param val The value to truncate
+ *
+ * Truncate according to rstyle. If val is already near an integer in
+ * terms of epsilon, the result will be that integer instead of the real
+ * truncated value.
+ */
+ template<class I>
+ I trunc(const ValueType &val) const;
+
+ };
+
+} //namespace Dune
+
+#include "float_cmp.cc"
+
+#endif //DUNE_COMMON_FLOAT_CMP_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+#ifndef DUNE_FMATRIX_HH
+#define DUNE_FMATRIX_HH
+
+#include <cmath>
+#include <cstddef>
+#include <iostream>
+
+#include <dune/common/exceptions.hh>
+#include <dune/common/fvector.hh>
+#include <dune/common/densematrix.hh>
+#include <dune/common/precision.hh>
+#include <dune/common/static_assert.hh>
+#include <dune/common/std/constexpr.hh>
+
+namespace Dune
+{
+
+ /**
+ @addtogroup DenseMatVec
+ @{
+ */
+
+ /*! \file
+
+ \brief Implements a matrix constructed from a given type
+ representing a field and compile-time given number of rows and columns.
+ */
+
+ template< class K, int ROWS, int COLS > class FieldMatrix;
+
+ template< class K, int ROWS, int COLS >
+ struct DenseMatVecTraits< FieldMatrix<K,ROWS,COLS> >
+ {
+ typedef FieldMatrix<K,ROWS,COLS> derived_type;
+
+ // each row is implemented by a field vector
+ typedef FieldVector<K,COLS> row_type;
+
+ typedef row_type &row_reference;
+ typedef const row_type &const_row_reference;
+
+ typedef Dune::array<row_type,ROWS> container_type;
+ typedef K value_type;
+ typedef typename container_type::size_type size_type;
+ };
+
+ template< class K, int ROWS, int COLS >
+ struct FieldTraits< FieldMatrix<K,ROWS,COLS> >
+ {
+ typedef typename FieldTraits<K>::field_type field_type;
+ typedef typename FieldTraits<K>::real_type real_type;
+ };
+
+ /**
+ @brief A dense n x m matrix.
+
+ Matrices represent linear maps from a vector space V to a vector space W.
+ This class represents such a linear map by storing a two-dimensional
+ %array of numbers of a given field type K. The number of rows and
+ columns is given at compile time.
+ */
+ template<class K, int ROWS, int COLS>
+ class FieldMatrix : public DenseMatrix< FieldMatrix<K,ROWS,COLS> >
+ {
+ Dune::array< FieldVector<K,COLS>, ROWS > _data;
+ typedef DenseMatrix< FieldMatrix<K,ROWS,COLS> > Base;
+ public:
+
+ //! export size
+ enum {
+ //! The number of rows.
+ rows = ROWS,
+ //! The number of columns.
+ cols = COLS
+ };
+
+ typedef typename Base::size_type size_type;
+ typedef typename Base::row_type row_type;
+
+ typedef typename Base::row_reference row_reference;
+ typedef typename Base::const_row_reference const_row_reference;
+
+ //===== constructors
+ /** \brief Default constructor
+ */
+ FieldMatrix () {}
+
+ /** \brief Constructor initializing the whole matrix with a scalar
+ */
+ template< class Other >
+ FieldMatrix ( const Other &other )
+ {
+ DenseMatrixAssigner< FieldMatrix< K, ROWS, COLS >, Other >::apply( *this, other );
+ }
+
+ //===== assignment
+ using Base::operator=;
+
+ // To be removed!
+#if 0
+ //! Multiplies M from the left to this matrix
+ FieldMatrix& leftmultiply (const FieldMatrix<K,rows,rows>& M)
+ {
+ FieldMatrix<K,rows,cols> C(*this);
+
+ for (size_type i=0; i<rows; i++)
+ for (size_type j=0; j<cols; j++) {
+ (*this)[i][j] = 0;
+ for (size_type k=0; k<rows; k++)
+ (*this)[i][j] += M[i][k]*C[k][j];
+ }
+
+ return *this;
+ }
+#endif
+
+ //! Multiplies M from the left to this matrix, this matrix is not modified
+ template<int l>
+ FieldMatrix<K,l,cols> leftmultiplyany (const FieldMatrix<K,l,rows>& M) const
+ {
+ FieldMatrix<K,l,cols> C;
+
+ for (size_type i=0; i<l; i++) {
+ for (size_type j=0; j<cols; j++) {
+ C[i][j] = 0;
+ for (size_type k=0; k<rows; k++)
+ C[i][j] += M[i][k]*(*this)[k][j];
+ }
+ }
+ return C;
+ }
+
+ //! Multiplies M from the right to this matrix
+ FieldMatrix& rightmultiply (const FieldMatrix<K,cols,cols>& M)
+ {
+ FieldMatrix<K,rows,cols> C(*this);
+
+ for (size_type i=0; i<rows; i++)
+ for (size_type j=0; j<cols; j++) {
+ (*this)[i][j] = 0;
+ for (size_type k=0; k<cols; k++)
+ (*this)[i][j] += C[i][k]*M[k][j];
+ }
+ return *this;
+ }
+
+ //! Multiplies M from the right to this matrix, this matrix is not modified
+ template<int l>
+ FieldMatrix<K,rows,l> rightmultiplyany (const FieldMatrix<K,cols,l>& M) const
+ {
+ FieldMatrix<K,rows,l> C;
+
+ for (size_type i=0; i<rows; i++) {
+ for (size_type j=0; j<l; j++) {
+ C[i][j] = 0;
+ for (size_type k=0; k<cols; k++)
+ C[i][j] += (*this)[i][k]*M[k][j];
+ }
+ }
+ return C;
+ }
+
+ // make this thing a matrix
+ DUNE_CONSTEXPR size_type mat_rows() const { return ROWS; }
+ DUNE_CONSTEXPR size_type mat_cols() const { return COLS; }
+
+ row_reference mat_access ( size_type i )
+ {
+ assert(i < ROWS);
+ return _data[i];
+ }
+
+ const_row_reference mat_access ( size_type i ) const
+ {
+ assert(i < ROWS);
+ return _data[i];
+ }
+ };
+
+#ifndef DOXYGEN // hide specialization
+ /** \brief Special type for 1x1 matrices
+ */
+ template<class K>
+ class FieldMatrix<K,1,1> : public DenseMatrix< FieldMatrix<K,1,1> >
+ {
+ FieldVector<K,1> _data;
+ typedef DenseMatrix< FieldMatrix<K,1,1> > Base;
+ public:
+ // standard constructor and everything is sufficient ...
+
+ //===== type definitions and constants
+
+ //! The type used for index access and size operations
+ typedef typename Base::size_type size_type;
+
+ //! We are at the leaf of the block recursion
+ enum {
+ //! The number of block levels we contain.
+ //! This is always one for this type.
+ blocklevel = 1
+ };
+
+ typedef typename Base::row_type row_type;
+
+ typedef typename Base::row_reference row_reference;
+ typedef typename Base::const_row_reference const_row_reference;
+
+ //! export size
+ enum {
+ //! \brief The number of rows.
+ //! This is always one for this type.
+ rows = 1,
+ //! \brief The number of columns.
+ //! This is always one for this type.
+ cols = 1
+ };
+
+ //===== constructors
+ /** \brief Default constructor
+ */
+ FieldMatrix () {}
+
+ /** \brief Constructor initializing the whole matrix with a scalar
+ */
+ FieldMatrix (const K& k)
+ {
+ _data[0] = k;
+ }
+
+ template< class Other >
+ FieldMatrix ( const Other &other )
+ {
+ DenseMatrixAssigner< FieldMatrix< K, 1, 1 >, Other >::apply( *this, other );
+ }
+
+ //===== solve
+
+ //! Multiplies M from the left to this matrix, this matrix is not modified
+ template<int l>
+ FieldMatrix<K,l,1> leftmultiplyany (const FieldMatrix<K,l,1>& M) const
+ {
+ FieldMatrix<K,l,1> C;
+ for (size_type j=0; j<l; j++)
+ C[j][0] = M[j][0]*(*this)[0][0];
+ return C;
+ }
+
+ //! left multiplication
+ FieldMatrix& rightmultiply (const FieldMatrix& M)
+ {
+ _data[0] *= M[0][0];
+ return *this;
+ }
+
+ //! Multiplies M from the right to this matrix, this matrix is not modified
+ template<int l>
+ FieldMatrix<K,1,l> rightmultiplyany (const FieldMatrix<K,1,l>& M) const
+ {
+ FieldMatrix<K,1,l> C;
+
+ for (size_type j=0; j<l; j++)
+ C[0][j] = M[0][j]*_data[0];
+ return C;
+ }
+
+ // make this thing a matrix
+ DUNE_CONSTEXPR size_type mat_rows() const { return 1; }
+ DUNE_CONSTEXPR size_type mat_cols() const { return 1; }
+
+ row_reference mat_access ( size_type i )
+ {
+ assert(i == 0);
+ return _data;
+ }
+
+ const_row_reference mat_access ( size_type i ) const
+ {
+ assert(i == 0);
+ return _data;
+ }
+
+ //! add scalar
+ FieldMatrix& operator+= (const K& k)
+ {
+ _data[0] += k;
+ return (*this);
+ }
+
+ //! subtract scalar
+ FieldMatrix& operator-= (const K& k)
+ {
+ _data[0] -= k;
+ return (*this);
+ }
+
+ //! multiplication with scalar
+ FieldMatrix& operator*= (const K& k)
+ {
+ _data[0] *= k;
+ return (*this);
+ }
+
+ //! division by scalar
+ FieldMatrix& operator/= (const K& k)
+ {
+ _data[0] /= k;
+ return (*this);
+ }
+
+ //===== conversion operator
+
+ operator K () const { return _data[0]; }
+
+ };
+
+ /** \brief Sends the matrix to an output stream */
+ template<typename K>
+ std::ostream& operator<< (std::ostream& s, const FieldMatrix<K,1,1>& a)
+ {
+ s << a[0][0];
+ return s;
+ }
+
+#endif // DOXYGEN
+
+ namespace FMatrixHelp {
+
+ //! invert scalar without changing the original matrix
+ template <typename K>
+ static inline K invertMatrix (const FieldMatrix<K,1,1> &matrix, FieldMatrix<K,1,1> &inverse)
+ {
+ inverse[0][0] = 1.0/matrix[0][0];
+ return matrix[0][0];
+ }
+
+ //! invert scalar without changing the original matrix
+ template <typename K>
+ static inline K invertMatrix_retTransposed (const FieldMatrix<K,1,1> &matrix, FieldMatrix<K,1,1> &inverse)
+ {
+ return invertMatrix(matrix,inverse);
+ }
+
+
+ //! invert 2x2 Matrix without changing the original matrix
+ template <typename K>
+ static inline K invertMatrix (const FieldMatrix<K,2,2> &matrix, FieldMatrix<K,2,2> &inverse)
+ {
+ // code generated by maple
+ K det = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
+ K det_1 = 1.0/det;
+ inverse[0][0] = matrix[1][1] * det_1;
+ inverse[0][1] = - matrix[0][1] * det_1;
+ inverse[1][0] = - matrix[1][0] * det_1;
+ inverse[1][1] = matrix[0][0] * det_1;
+ return det;
+ }
+
+ //! invert 2x2 Matrix without changing the original matrix
+ //! return transposed matrix
+ template <typename K>
+ static inline K invertMatrix_retTransposed (const FieldMatrix<K,2,2> &matrix, FieldMatrix<K,2,2> &inverse)
+ {
+ // code generated by maple
+ K det = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
+ K det_1 = 1.0/det;
+ inverse[0][0] = matrix[1][1] * det_1;
+ inverse[1][0] = - matrix[0][1] * det_1;
+ inverse[0][1] = - matrix[1][0] * det_1;
+ inverse[1][1] = matrix[0][0] * det_1;
+ return det;
+ }
+
+ //! invert 3x3 Matrix without changing the original matrix
+ template <typename K>
+ static inline K invertMatrix (const FieldMatrix<K,3,3> &matrix, FieldMatrix<K,3,3> &inverse)
+ {
+ // code generated by maple
+ K t4 = matrix[0][0] * matrix[1][1];
+ K t6 = matrix[0][0] * matrix[1][2];
+ K t8 = matrix[0][1] * matrix[1][0];
+ K t10 = matrix[0][2] * matrix[1][0];
+ K t12 = matrix[0][1] * matrix[2][0];
+ K t14 = matrix[0][2] * matrix[2][0];
+
+ K det = (t4*matrix[2][2]-t6*matrix[2][1]-t8*matrix[2][2]+
+ t10*matrix[2][1]+t12*matrix[1][2]-t14*matrix[1][1]);
+ K t17 = 1.0/det;
+
+ inverse[0][0] = (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1])*t17;
+ inverse[0][1] = -(matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1])*t17;
+ inverse[0][2] = (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])*t17;
+ inverse[1][0] = -(matrix[1][0] * matrix[2][2] - matrix[1][2] * matrix[2][0])*t17;
+ inverse[1][1] = (matrix[0][0] * matrix[2][2] - t14) * t17;
+ inverse[1][2] = -(t6-t10) * t17;
+ inverse[2][0] = (matrix[1][0] * matrix[2][1] - matrix[1][1] * matrix[2][0]) * t17;
+ inverse[2][1] = -(matrix[0][0] * matrix[2][1] - t12) * t17;
+ inverse[2][2] = (t4-t8) * t17;
+
+ return det;
+ }
+
+ //! invert 3x3 Matrix without changing the original matrix
+ template <typename K>
+ static inline K invertMatrix_retTransposed (const FieldMatrix<K,3,3> &matrix, FieldMatrix<K,3,3> &inverse)
+ {
+ // code generated by maple
+ K t4 = matrix[0][0] * matrix[1][1];
+ K t6 = matrix[0][0] * matrix[1][2];
+ K t8 = matrix[0][1] * matrix[1][0];
+ K t10 = matrix[0][2] * matrix[1][0];
+ K t12 = matrix[0][1] * matrix[2][0];
+ K t14 = matrix[0][2] * matrix[2][0];
+
+ K det = (t4*matrix[2][2]-t6*matrix[2][1]-t8*matrix[2][2]+
+ t10*matrix[2][1]+t12*matrix[1][2]-t14*matrix[1][1]);
+ K t17 = 1.0/det;
+
+ inverse[0][0] = (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1])*t17;
+ inverse[1][0] = -(matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1])*t17;
+ inverse[2][0] = (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])*t17;
+ inverse[0][1] = -(matrix[1][0] * matrix[2][2] - matrix[1][2] * matrix[2][0])*t17;
+ inverse[1][1] = (matrix[0][0] * matrix[2][2] - t14) * t17;
+ inverse[2][1] = -(t6-t10) * t17;
+ inverse[0][2] = (matrix[1][0] * matrix[2][1] - matrix[1][1] * matrix[2][0]) * t17;
+ inverse[1][2] = -(matrix[0][0] * matrix[2][1] - t12) * t17;
+ inverse[2][2] = (t4-t8) * t17;
+
+ return det;
+ }
+
+ //! calculates ret = A * B
+ template< class K, int m, int n, int p >
+ static inline void multMatrix ( const FieldMatrix< K, m, n > &A,
+ const FieldMatrix< K, n, p > &B,
+ FieldMatrix< K, m, p > &ret )
+ {
+ typedef typename FieldMatrix< K, m, p > :: size_type size_type;
+
+ for( size_type i = 0; i < m; ++i )
+ {
+ for( size_type j = 0; j < p; ++j )
+ {
+ ret[ i ][ j ] = K( 0 );
+ for( size_type k = 0; k < n; ++k )
+ ret[ i ][ j ] += A[ i ][ k ] * B[ k ][ j ];
+ }
+ }
+ }
+
+ //! calculates ret= A_t*A
+ template <typename K, int rows, int cols>
+ static inline void multTransposedMatrix(const FieldMatrix<K,rows,cols> &matrix, FieldMatrix<K,cols,cols>& ret)
+ {
+ typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
+
+ for(size_type i=0; i<cols; i++)
+ for(size_type j=0; j<cols; j++)
+ {
+ ret[i][j]=0.0;
+ for(size_type k=0; k<rows; k++)
+ ret[i][j]+=matrix[k][i]*matrix[k][j];
+ }
+ }
+
+#if 0
+ //! calculates ret = matrix * x
+ template <typename K, int rows, int cols>
+ static inline void multAssign(const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,cols> & x, FieldVector<K,rows> & ret)
+ {
+ typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
+
+ for(size_type i=0; i<rows; ++i)
+ {
+ ret[i] = 0.0;
+ for(size_type j=0; j<cols; ++j)
+ {
+ ret[i] += matrix[i][j]*x[j];
+ }
+ }
+ }
+#else
+ using Dune::DenseMatrixHelp::multAssign;
+#endif
+
+ //! calculates ret = matrix^T * x
+ template <typename K, int rows, int cols>
+ static inline void multAssignTransposed( const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,rows> & x, FieldVector<K,cols> & ret)
+ {
+ typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
+
+ for(size_type i=0; i<cols; ++i)
+ {
+ ret[i] = 0.0;
+ for(size_type j=0; j<rows; ++j)
+ ret[i] += matrix[j][i]*x[j];
+ }
+ }
+
+ //! calculates ret = matrix * x
+ template <typename K, int rows, int cols>
+ static inline FieldVector<K,rows> mult(const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,cols> & x)
+ {
+ FieldVector<K,rows> ret;
+ multAssign(matrix,x,ret);
+ return ret;
+ }
+
+ //! calculates ret = matrix^T * x
+ template <typename K, int rows, int cols>
+ static inline FieldVector<K,cols> multTransposed(const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,rows> & x)
+ {
+ FieldVector<K,cols> ret;
+ multAssignTransposed( matrix, x, ret );
+ return ret;
+ }
+
+ } // end namespace FMatrixHelp
+
+ /** @} end documentation */
+
+} // end namespace
+
+#include "fmatrixev.hh"
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_FMATRIXEIGENVALUES_CC
+#define DUNE_FMATRIXEIGENVALUES_CC
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <iostream>
+#include <cmath>
+#include <cassert>
+
+#include <dune/common/exceptions.hh>
+
+#if HAVE_LAPACK
+
+// symmetric matrices
+#define DSYEV_FORTRAN FC_FUNC (dsyev, DSYEV)
+
+// nonsymmetric matrices
+#define DGEEV_FORTRAN FC_FUNC (dgeev, DGEEV)
+
+// dsyev declaration (in liblapack)
+extern "C" {
+
+ /*
+ *
+ ** purpose
+ ** =======
+ **
+ ** xsyev computes all eigenvalues and, optionally, eigenvectors of a
+ ** BASE DATA TYPE symmetric matrix a.
+ **
+ ** arguments
+ ** =========
+ **
+ ** jobz (input) char
+ ** = 'n': compute eigenvalues only;
+ ** = 'v': compute eigenvalues and eigenvectors.
+ **
+ ** uplo (input) char
+ ** = 'u': upper triangle of a is stored;
+ ** = 'l': lower triangle of a is stored.
+ **
+ ** n (input) long int
+ ** the order of the matrix a. n >= 0.
+ **
+ ** a (input/output) BASE DATA TYPE array, dimension (lda, n)
+ ** on entry, the symmetric matrix a. if uplo = 'u', the
+ ** leading n-by-n upper triangular part of a contains the
+ ** upper triangular part of the matrix a. if uplo = 'l',
+ ** the leading n-by-n lower triangular part of a contains
+ ** the lower triangular part of the matrix a.
+ ** on exit, if jobz = 'v', then if info = 0, a contains the
+ ** orthonormal eigenvectors of the matrix a.
+ ** if jobz = 'n', then on exit the lower triangle (if uplo='l')
+ ** or the upper triangle (if uplo='u') of a, including the
+ ** diagonal, is destroyed.
+ **
+ ** lda (input) long int
+ ** the leading dimension of the array a. lda >= max(1,n).
+ **
+ ** w (output) BASE DATA TYPE array, dimension (n)
+ ** if info = 0, the eigenvalues in ascending order.
+ **
+ **
+ **
+ ** info (output) long int
+ ** = 0: successful exit
+ ** < 0: if info = -i, the i-th argument had an illegal value
+ ** > 0: if info = i, the algorithm failed to converge; i
+ ** off-diagonal elements of an intermediate tridiagonal
+ ** form did not converge to zero.
+ **
+ **/
+ extern void DSYEV_FORTRAN(const char* jobz, const char* uplo, const long
+ int* n, double* a, const long int* lda, double* w,
+ double* work, const long int* lwork, long int* info);
+
+ /*
+ *
+ ** purpose
+ ** =======
+ **
+ ** xgeev computes for an N-by-N BASE DATA TYPE nonsymmetric matrix A, the
+ ** eigenvalues and, optionally, the left and/or right eigenvectors.
+ **
+ ** The right eigenvector v(j) of A satisfies
+ ** A * v(j) = lambda(j) * v(j)
+ ** where lambda(j) is its eigenvalue.
+ ** The left eigenvector u(j) of A satisfies
+ ** u(j)**T * A = lambda(j) * u(j)**T
+ ** where u(j)**T denotes the transpose of u(j).
+ **
+ ** The computed eigenvectors are normalized to have Euclidean norm
+ ** equal to 1 and largest component real.
+ **
+ ** arguments
+ ** =========
+ **
+ ** jobvl (input) char
+ ** = 'n': left eigenvectors of a are not computed;
+ ** = 'v': left eigenvectors of a are computed.
+ **
+ ** jobvr (input) char
+ ** = 'n': right eigenvectors of a are not computed;
+ ** = 'v': right eigenvectors of a are computed.
+ **
+ ** n (input) long int
+ ** the order of the matrix v. v >= 0.
+ **
+ ** a (input/output) BASE DATA TYPE array, dimension (lda,n)
+ ** on entry, the n-by-n matrix a.
+ ** on exit, a has been overwritten.
+ **
+ ** lda (input) long int
+ ** the leading dimension of the array a. lda >= max(1,n).
+ **
+ ** wr (output) BASE DATA TYPE array, dimension (n)
+ ** wi (output) BASE DATA TYPE array, dimension (n)
+ ** wr and wi contain the real and imaginary parts,
+ ** respectively, of the computed eigenvalues. complex
+ ** conjugate pairs of eigenvalues appear consecutively
+ ** with the eigenvalue having the positive imaginary part
+ ** first.
+ **
+ ** vl (output) COMPLEX DATA TYPE array, dimension (ldvl,n)
+ ** if jobvl = 'v', the left eigenvectors u(j) are stored one
+ ** after another in the columns of vl, in the same order
+ ** as their eigenvalues.
+ ** if jobvl = 'n', vl is not referenced.
+ ** if the j-th eigenvalue is real, then u(j) = vl(:,j),
+ ** the j-th column of vl.
+ ** if the j-th and (j+1)-st eigenvalues form a complex
+ ** conjugate pair, then u(j) = vl(:,j) + i*vl(:,j+1) and
+ ** u(j+1) = vl(:,j) - i*vl(:,j+1).
+ **
+ ** ldvl (input) long int
+ ** the leading dimension of the array vl. ldvl >= 1; if
+ ** jobvl = 'v', ldvl >= n.
+ **
+ ** vr (output) COMPLEX DATA TYPE array, dimension (ldvr,n)
+ ** if jobvr = 'v', the right eigenvectors v(j) are stored one
+ ** after another in the columns of vr, in the same order
+ ** as their eigenvalues.
+ ** if jobvr = 'n', vr is not referenced.
+ ** if the j-th eigenvalue is real, then v(j) = vr(:,j),
+ ** the j-th column of vr.
+ ** if the j-th and (j+1)-st eigenvalues form a complex
+ ** conjugate pair, then v(j) = vr(:,j) + i*vr(:,j+1) and
+ ** v(j+1) = vr(:,j) - i*vr(:,j+1).
+ **
+ ** ldvr (input) long int
+ ** the leading dimension of the array vr. ldvr >= 1; if
+ ** jobvr = 'v', ldvr >= n.
+ **
+ ** work (workspace/output) BASE DATA TYPE array, dimension (max(1,lwork))
+ ** on exit, if info = 0, work(1) returns the optimal lwork.
+ **
+ ** lwork (input) long int
+ ** the dimension of the array work. lwork >= max(1,3*n), and
+ ** if jobvl = 'v' or jobvr = 'v', lwork >= 4*n. for good
+ ** performance, lwork must generally be larger.
+ **
+ ** if lwork = -1, then a workspace query is assumed; the routine
+ ** only calculates the optimal size of the work array, returns
+ ** this value as the first entry of the work array, and no error
+ ** message related to lwork is issued by xerbla.
+ **
+ ** info (output) long int
+ ** = 0: successful exit
+ ** < 0: if info = -i, the i-th argument had an illegal value.
+ ** > 0: if info = i, the qr algorithm failed to compute all the
+ ** eigenvalues, and no eigenvectors have been computed;
+ ** elements i+1:n of wr and wi contain eigenvalues which
+ ** have converged.
+ **
+ **/
+
+ extern void DGEEV_FORTRAN(const char* jobvl, const char* jobvr, const long
+ int* n, double* a, const long int* lda, double* wr, double* wi, double* vl,
+ const long int* ldvl, double* vr, const long int* ldvr, double* work,
+ const long int* lwork, const long int* info);
+
+} // end extern C
+#endif
+
+namespace Dune {
+
+ namespace FMatrixHelp {
+
+ void eigenValuesLapackCall(
+ const char* jobz, const char* uplo, const long
+ int* n, double* a, const long int* lda, double* w,
+ double* work, const long int* lwork, long int* info)
+ {
+#if HAVE_LAPACK
+ // call LAPACK dsyev
+ DSYEV_FORTRAN(jobz, uplo, n, a, lda, w, work, lwork, info);
+#else
+ DUNE_THROW(NotImplemented,"eigenValuesLapackCall: LAPACK not found!");
+#endif
+ }
+
+ void eigenValuesNonsymLapackCall(
+ const char* jobvl, const char* jobvr, const long
+ int* n, double* a, const long int* lda, double* wr, double* wi, double* vl,
+ const long int* ldvl, double* vr, const long int* ldvr, double* work,
+ const long int* lwork, const long int* info)
+ {
+#if HAVE_LAPACK
+ // call LAPACK dgeev
+ DGEEV_FORTRAN(jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr, ldvr,
+ work, lwork, info);
+#else
+ DUNE_THROW(NotImplemented,"eigenValuesNonsymLapackCall: LAPACK not found!");
+#endif
+ }
+
+ } // end namespace FMatrixHelp
+
+} // end namespace Dune
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_FMATRIXEIGENVALUES_HH
+#define DUNE_FMATRIXEIGENVALUES_HH
+
+/** \file
+ * \brief Eigenvalue computations for the FieldMatrix class
+ */
+
+#include <iostream>
+#include <cmath>
+#include <cassert>
+
+#include <dune/common/exceptions.hh>
+#include <dune/common/fvector.hh>
+#include <dune/common/fmatrix.hh>
+
+namespace Dune {
+
+ /**
+ @addtogroup DenseMatVec
+ @{
+ */
+
+ namespace FMatrixHelp {
+
+ // defined in fmatrixev.cc
+ extern void eigenValuesLapackCall(
+ const char* jobz, const char* uplo, const long
+ int* n, double* a, const long int* lda, double* w,
+ double* work, const long int* lwork, long int* info);
+
+ extern void eigenValuesNonsymLapackCall(
+ const char* jobvl, const char* jobvr, const long
+ int* n, double* a, const long int* lda, double* wr, double* wi, double* vl,
+ const long int* ldvl, double* vr, const long int* ldvr, double* work,
+ const long int* lwork, const long int* info);
+
+ /** \brief calculates the eigenvalues of a symmetric field matrix
+ \param[in] matrix matrix eigenvalues are calculated for
+ \param[out] eigenvalues FieldVector that contains eigenvalues in
+ ascending order
+ */
+ template <typename K>
+ static void eigenValues(const FieldMatrix<K, 1, 1>& matrix,
+ FieldVector<K, 1>& eigenvalues)
+ {
+ eigenvalues[0] = matrix[0][0];
+ }
+
+ /** \brief calculates the eigenvalues of a symmetric field matrix
+ \param[in] matrix matrix eigenvalues are calculated for
+ \param[out] eigenvalues FieldVector that contains eigenvalues in
+ ascending order
+ */
+ template <typename K>
+ static void eigenValues(const FieldMatrix<K, 2, 2>& matrix,
+ FieldVector<K, 2>& eigenvalues)
+ {
+ const K detM = matrix[0][0] * matrix[1][1] - matrix[1][0] * matrix[0][1];
+ const K p = 0.5 * (matrix[0][0] + matrix [1][1]);
+ K q = p * p - detM;
+ if( q < 0 && q > -1e-14 ) q = 0;
+ if (p < 0 || q < 0)
+ {
+ std::cout << p << " p | q " << q << "\n";
+ std::cout << matrix << std::endl;
+ std::cout << "something went wrong in Eigenvalues for matrix!" << std::endl;
+ assert(false);
+ abort();
+ }
+
+ // get square root
+ q = std :: sqrt(q);
+
+ // store eigenvalues in ascending order
+ eigenvalues[0] = p - q;
+ eigenvalues[1] = p + q;
+ }
+
+ /** \brief calculates the eigenvalues of a symmetric field matrix
+ \param[in] matrix matrix eigenvalues are calculated for
+ \param[out] eigenvalues FieldVector that contains eigenvalues in
+ ascending order
+
+ \note LAPACK::dsyev is used to calculate the eigenvalues
+ */
+ template <int dim, typename K>
+ static void eigenValues(const FieldMatrix<K, dim, dim>& matrix,
+ FieldVector<K, dim>& eigenvalues)
+ {
+ {
+ const long int N = dim ;
+ const char jobz = 'n'; // only calculate eigenvalues
+ const char uplo = 'u'; // use upper triangular matrix
+
+ // length of matrix vector
+ const long int w = N * N ;
+
+ // matrix to put into dsyev
+ double matrixVector[dim * dim];
+
+ // copy matrix
+ int row = 0;
+ for(int i=0; i<dim; ++i)
+ {
+ for(int j=0; j<dim; ++j, ++row)
+ {
+ matrixVector[ row ] = matrix[ i ][ j ];
+ }
+ }
+
+ // working memory
+ double workSpace[dim * dim];
+
+ // return value information
+ long int info = 0;
+
+ // call LAPACK routine (see fmatrixev.cc)
+ eigenValuesLapackCall(&jobz, &uplo, &N, &matrixVector[0], &N,
+ &eigenvalues[0], &workSpace[0], &w, &info);
+
+ if( info != 0 )
+ {
+ std::cerr << "For matrix " << matrix << " eigenvalue calculation failed! " << std::endl;
+ DUNE_THROW(InvalidStateException,"eigenValues: Eigenvalue calculation failed!");
+ }
+ }
+ }
+ /** \brief calculates the eigenvalues of a symmetric field matrix
+ \param[in] matrix matrix eigenvalues are calculated for
+ \param[out] eigenValues FieldVector that contains eigenvalues in
+ ascending order
+
+ \note LAPACK::dgeev is used to calculate the eigen values
+ */
+ template <int dim, typename K, class C>
+ static void eigenValuesNonSym(const FieldMatrix<K, dim, dim>& matrix,
+ FieldVector<C, dim>& eigenValues)
+ {
+ {
+ const long int N = dim ;
+ const char jobvl = 'n';
+ const char jobvr = 'n';
+
+ // matrix to put into dgeev
+ double matrixVector[dim * dim];
+
+ // copy matrix
+ int row = 0;
+ for(int i=0; i<dim; ++i)
+ {
+ for(int j=0; j<dim; ++j, ++row)
+ {
+ matrixVector[ row ] = matrix[ i ][ j ];
+ }
+ }
+
+ // working memory
+ double eigenR[dim];
+ double eigenI[dim];
+ double work[3*dim];
+
+ // return value information
+ long int info = 0;
+ long int lwork = 3*dim;
+
+ // call LAPACK routine (see fmatrixev_ext.cc)
+ eigenValuesNonsymLapackCall(&jobvl, &jobvr, &N, &matrixVector[0], &N,
+ &eigenR[0], &eigenI[0], 0, &N, 0, &N, &work[0],
+ &lwork, &info);
+
+ if( info != 0 )
+ {
+ std::cerr << "For matrix " << matrix << " eigenvalue calculation failed! " << std::endl;
+ DUNE_THROW(InvalidStateException,"eigenValues: Eigenvalue calculation failed!");
+ }
+ for (int i=0; i<N; ++i) {
+ eigenValues[i].real = eigenR[i];
+ eigenValues[i].imag = eigenI[i];
+ }
+ }
+
+ }
+
+ } // end namespace FMatrixHelp
+
+ /** @} end documentation */
+
+} // end namespace Dune
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+
+#ifndef DUNE_COMMON_FORLOOP_HH
+#define DUNE_COMMON_FORLOOP_HH
+
+/** \file
+ * \brief A static for loop for template meta-programming
+ */
+
+#include <dune/common/static_assert.hh>
+
+namespace Dune
+{
+
+#ifndef DOXYGEN
+ // GenericForLoop
+ // --------------
+
+ template< template< class, class > class Operation, template< int > class Value, int first, int last >
+ class GenericForLoop
+ : public Operation< Value< first >, GenericForLoop< Operation, Value, first+1, last > >
+ {
+ dune_static_assert( (first <= last), "GenericForLoop: first > last" );
+ };
+
+ template< template< class, class > class Operation, template< int > class Value, int last >
+ class GenericForLoop< Operation, Value, last, last >
+ : public Value< last >
+ {};
+
+ // ForLoopHelper
+ // -------------
+
+ namespace ForLoopHelper
+ {
+
+ template< class A, class B >
+ struct Apply
+ {
+ static void apply ()
+ {
+ A::apply();
+ B::apply();
+ }
+
+ template< class T1 >
+ static void apply ( T1 &p1 )
+ {
+ A::apply( p1 );
+ B::apply( p1 );
+ }
+
+ template< class T1, class T2 >
+ static void apply ( T1 &p1, T2 &p2 )
+ {
+ A::apply( p1, p2 );
+ B::apply( p1, p2 );
+ }
+
+ template< class T1, class T2, class T3 >
+ static void apply ( T1 &p1, T2 &p2, T3 &p3 )
+ {
+ A::apply( p1, p2, p3 );
+ B::apply( p1, p2, p3 );
+ }
+
+ template< class T1, class T2, class T3, class T4 >
+ static void apply ( T1 &p1, T2 &p2, T3 &p3, T4 &p4 )
+ {
+ A::apply( p1, p2, p3, p4 );
+ B::apply( p1, p2, p3, p4 );
+ }
+
+ template< class T1, class T2, class T3, class T4, class T5 >
+ static void apply ( T1 &p1, T2 &p2, T3 &p3, T4 &p4, T5 &p5 )
+ {
+ A::apply( p1, p2, p3, p4, p5 );
+ B::apply( p1, p2, p3, p4, p5 );
+ }
+
+ template< class T1, class T2, class T3, class T4, class T5, class T6 >
+ static void apply ( T1 &p1, T2 &p2, T3 &p3, T4 &p4, T5 &p5, T6 &p6 )
+ {
+ A::apply( p1, p2, p3, p4, p5, p6 );
+ B::apply( p1, p2, p3, p4, p5, p6 );
+ }
+
+ template< class T1, class T2, class T3, class T4, class T5, class T6,
+ class T7 >
+ static void apply ( T1 &p1, T2 &p2, T3 &p3, T4 &p4, T5 &p5, T6 &p6,
+ T7 &p7 )
+ {
+ A::apply( p1, p2, p3, p4, p5, p6, p7 );
+ B::apply( p1, p2, p3, p4, p5, p6, p7 );
+ }
+
+ template< class T1, class T2, class T3, class T4, class T5, class T6,
+ class T7, class T8 >
+ static void apply ( T1 &p1, T2 &p2, T3 &p3, T4 &p4, T5 &p5, T6 &p6,
+ T7 &p7, T8 &p8 )
+ {
+ A::apply( p1, p2, p3, p4, p5, p6, p7, p8 );
+ B::apply( p1, p2, p3, p4, p5, p6, p7, p8 );
+ }
+
+ template< class T1, class T2, class T3, class T4, class T5, class T6,
+ class T7, class T8, class T9 >
+ static void apply ( T1 &p1, T2 &p2, T3 &p3, T4 &p4, T5 &p5, T6 &p6,
+ T7 &p7, T8 &p8, T9 &p9 )
+ {
+ A::apply( p1, p2, p3, p4, p5, p6, p7, p8, p9 );
+ B::apply( p1, p2, p3, p4, p5, p6, p7, p8, p9 );
+ }
+
+ template< class T1, class T2, class T3, class T4, class T5, class T6,
+ class T7, class T8, class T9, class T10 >
+ static void apply ( T1 &p1, T2 &p2, T3 &p3, T4 &p4, T5 &p5, T6 &p6,
+ T7 &p7, T8 &p8, T9 &p9, T10 &p10 )
+ {
+ A::apply( p1, p2, p3, p4, p5, p6, p7, p8, p9, p10 );
+ B::apply( p1, p2, p3, p4, p5, p6, p7, p8, p9, p10 );
+ }
+
+ template< class T1, class T2, class T3, class T4, class T5, class T6,
+ class T7, class T8, class T9, class T10, class T11 >
+ static void apply ( T1 &p1, T2 &p2, T3 &p3, T4 &p4, T5 &p5, T6 &p6,
+ T7 &p7, T8 &p8, T9 &p9, T10 &p10, T11 &p11 )
+ {
+ A::apply( p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11 );
+ B::apply( p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11 );
+ }
+
+ template< class T1, class T2, class T3, class T4, class T5, class T6,
+ class T7, class T8, class T9, class T10, class T11, class T12 >
+ static void apply ( T1 &p1, T2 &p2, T3 &p3, T4 &p4, T5 &p5, T6 &p6,
+ T7 &p7, T8 &p8, T9 &p9, T10 &p10, T11 &p11,
+ T12 &p12 )
+ {
+ A::apply( p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12 );
+ B::apply( p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12 );
+ }
+
+ template< class T1, class T2, class T3, class T4, class T5, class T6,
+ class T7, class T8, class T9, class T10, class T11, class T12,
+ class T13>
+ static void apply ( T1 &p1, T2 &p2, T3 &p3, T4 &p4, T5 &p5, T6 &p6,
+ T7 &p7, T8 &p8, T9 &p9, T10 &p10, T11 &p11,
+ T12 &p12, T13 &p13 )
+ {
+ A::apply( p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13 );
+ B::apply( p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13 );
+ }
+ };
+
+ } // end namespace ForLoopHelper
+
+#endif
+
+
+ /** \class ForLoop
+ * @brief A static loop using TMP
+ *
+ * The ForLoop takes a
+ * \code template<int i> class Operation \endcode
+ * template argument with a static apply method
+ * which is called for i=first...last (first<=last are int template arguments).
+ * A specialization for class template class Operation for i=first
+ * or i=last is not required. The class Operation must provide a
+ * static void function apply(...). Arguments (as references)
+ * can be passed through the ForLoop to this function
+ * (up to 5 at the moment).
+ *
+ * It is possible to pass a subclass to the ForLoop
+ * (since no specialization is needed).
+ *
+ * Example of usage:
+ * \code
+ * template<class Tuple>
+ * struct PrintTupleTypes
+ * {
+ * template <int i>
+ * struct Operation
+ * {
+ * template<class Stream>
+ * static void apply(Stream &stream, const std::string &prefix)
+ * {
+ * stream << prefix << i << ": "
+ * << className<typename tuple_element<i, Tuple>::type>()
+ * << std::endl;
+ * }
+ * };
+ * template<class Stream>
+ * static void print(Stream &stream, const std::string &prefix)
+ * {
+ * // cannot attach on-the-fly in the argument to ForLoop<..>::apply() since
+ * // that would yield an rvalue
+ * std::string extended_prefix = prefix+" ";
+ *
+ * stream << prefix << "tuple<" << std::endl;
+ * ForLoop<Operation, 0, tuple_size<Tuple>::value-1>::
+ * apply(stream, extended_prefix);
+ * stream << prefix << ">" << std::endl;
+ * }
+ * };
+ * \endcode
+ *
+ * \note Don't use any rvalues as the arguments to apply().
+ *
+ * Rvalues will bind to const-references, but not to references that are
+ * non-const. Since we do want to support modifiable arguments to apply(),
+ * we have to use non-const references as arguments. Supporting const
+ * references as well would lead to an insane number of overloads which all
+ * have to be written more-or-less by hand.
+ *
+ * Examples of rvalues are: literals (1.0, 0, "huhu"), the results of
+ * functions returning an object (std::make_pair(0, 1.0)) and temporary
+ * object constructions (std::string("hello"));
+ */
+ template< template< int > class Operation, int first, int last >
+ class ForLoop
+ : public GenericForLoop< ForLoopHelper::Apply, Operation, first, last >
+ {
+ dune_static_assert( (first <= last), "ForLoop: first > last" );
+ };
+
+}
+
+#endif // #ifndef DUNE_COMMON_FORLOOP_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id: fvector.hh 5262 2008-09-07 09:03:38Z christi $
+#ifndef DUNE_FTRAITS_HH
+#define DUNE_FTRAITS_HH
+
+/** \file
+ * \brief Type traits to determine the type of reals (when working with complex numbers)
+ */
+
+#include <complex>
+
+namespace Dune {
+
+ /**
+ @addtogroup DenseMatVec
+ \brief Type traits to retrieve the field and the real type of classes
+
+ Type traits to retrieve the field and the real type of classes
+ e.g. that of FieldVector or FieldMatrix
+ */
+ template<class T>
+ struct FieldTraits
+ {
+ //! export the type representing the field
+ typedef T field_type;
+ //! export the type representing the real type of the field
+ typedef T real_type;
+ };
+
+ template<class T>
+ struct FieldTraits<const T>
+ {
+ typedef typename FieldTraits<T>::field_type field_type;
+ typedef typename FieldTraits<T>::real_type real_type;
+ };
+
+ template<class T>
+ struct FieldTraits< std::complex<T> >
+ {
+ typedef std::complex<T> field_type;
+ typedef T real_type;
+ };
+
+} // end namespace Dune
+
+#endif // DUNE_FTRAITS_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_FUNCTION_HH
+#define DUNE_FUNCTION_HH
+
+
+#include "typetraits.hh"
+
+namespace Dune {
+
+ /** @addtogroup Common
+ @{
+ */
+
+ /*! \file
+ \brief Simple base class templates for functions.
+ */
+
+ /**
+ * \brief Base class template for function classes
+ *
+ * \tparam Domain Type of input variable. This could be some 'const T' or 'const T&'.
+ *
+ * \tparam Range Type of output variable. This should be some non-const 'T&' to allow to return results.
+ */
+ template <class Domain, class Range>
+ class Function
+ {
+ typedef typename ConstantVolatileTraits<typename TypeTraits< Domain >::ReferredType >::UnqualifiedType RawDomainType;
+ typedef typename ConstantVolatileTraits<typename TypeTraits< Range >::ReferredType >::UnqualifiedType RawRangeType;
+
+ public:
+
+ //! Raw type of input variable with removed reference and constness
+ typedef RawRangeType RangeType;
+
+ //! Raw type of output variable with removed reference and constness
+ typedef RawDomainType DomainType;
+
+ //! Traits class containing raw types
+ struct Traits
+ {
+ typedef RawDomainType DomainType;
+ typedef RawRangeType RangeType;
+ };
+
+ /**
+ * \brief Function evaluation.
+ *
+ * \param x Argument for function evaluation.
+ * \param y Result of function evaluation.
+ */
+ void evaluate(const typename Traits::DomainType& x, typename Traits::RangeType& y) const;
+ }; // end of Function class
+
+
+
+ /**
+ * \brief Virtual base class template for function classes.
+ *
+ * \tparam DomainType The type of the input variable is 'const DomainType &'
+ *
+ * \tparam RangeType The type of the output variable is 'RangeType &'
+ */
+ template <class DomainType, class RangeType>
+ class VirtualFunction :
+ public Function<const DomainType&, RangeType&>
+ {
+ public:
+ typedef typename Function<const DomainType&, RangeType&>::Traits Traits;
+
+ virtual ~VirtualFunction() {}
+ /**
+ * \brief Function evaluation.
+ *
+ * \param x Argument for function evaluation.
+ * \param y Result of function evaluation.
+ */
+ virtual void evaluate(const typename Traits::DomainType& x, typename Traits::RangeType& y) const = 0;
+ }; // end of VirtualFunction class
+
+ /** @} end documentation */
+
+} // end namespace
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+#ifndef DUNE_FVECTOR_HH
+#define DUNE_FVECTOR_HH
+
+#include <cmath>
+#include <cstddef>
+#include <cstdlib>
+#include <complex>
+#include <cstring>
+#include <utility>
+
+#include <dune/common/std/constexpr.hh>
+
+#include "typetraits.hh"
+#include "exceptions.hh"
+#include "array.hh"
+#include "densevector.hh"
+#include "static_assert.hh"
+#include "unused.hh"
+
+namespace Dune {
+
+ /** @addtogroup DenseMatVec
+ @{
+ */
+
+ /*! \file
+ * \brief Implements a vector constructed from a given type
+ representing a field and a compile-time given size.
+ */
+
+ template< class K, int SIZE > class FieldVector;
+ template< class K, int SIZE >
+ struct DenseMatVecTraits< FieldVector<K,SIZE> >
+ {
+ typedef FieldVector<K,SIZE> derived_type;
+ typedef Dune::array<K,SIZE> container_type;
+ typedef K value_type;
+ typedef typename container_type::size_type size_type;
+ };
+
+ template< class K, int SIZE >
+ struct FieldTraits< FieldVector<K,SIZE> >
+ {
+ typedef typename FieldTraits<K>::field_type field_type;
+ typedef typename FieldTraits<K>::real_type real_type;
+ };
+
+ /**
+ * @brief TMP to check the size of a DenseVectors statically, if possible.
+ *
+ * If the implementation type of C is a FieldVector, we statically check
+ * whether its dimension is SIZE.
+ * @tparam C The implementation of the other DenseVector
+ * @tparam SIZE The size we need assume.
+ */
+ template<typename C, int SIZE>
+ struct IsFieldVectorSizeCorrect
+ {
+ enum {
+ /**
+ *@param True if C is not of type FieldVector or its dimension
+ * is not equal SIZE.
+ */
+ value = true
+ };
+ };
+
+ template<typename T, int SIZE>
+ struct IsFieldVectorSizeCorrect<FieldVector<T,SIZE>,SIZE>
+ {
+ enum {value = true};
+ };
+
+ template<typename T, int SIZE, int SIZE1>
+ struct IsFieldVectorSizeCorrect<FieldVector<T,SIZE1>,SIZE>
+ {
+ enum {value = false};
+ };
+
+
+ /** \brief vector space out of a tensor product of fields.
+ *
+ * \tparam K the field type (use float, double, complex, etc)
+ * \tparam SIZE number of components.
+ */
+ template< class K, int SIZE >
+ class FieldVector :
+ public DenseVector< FieldVector<K,SIZE> >
+ {
+ Dune::array<K,SIZE> _data;
+ typedef DenseVector< FieldVector<K,SIZE> > Base;
+ public:
+ //! export size
+ enum {
+ //! The size of this vector.
+ dimension = SIZE
+ };
+
+ typedef typename Base::size_type size_type;
+ typedef typename Base::value_type value_type;
+
+ //! Constructor making default-initialized vector
+ FieldVector()
+ // Use C++11 unified initialization if available - tends to generate
+ // fastest code
+#if HAVE_INITIALIZER_LIST
+ : _data{}
+ {}
+#else
+ {
+ // fall back to library approach - this gives faster code than array placement
+ // new. Apart from that, placement new may create problems if K is a complex
+ // type. In that case, the default constructor of the _data elements has already
+ // been called and may have allocated memory.
+ std::fill(_data.begin(),_data.end(),K());
+ }
+#endif
+
+ //! Constructor making vector with identical coordinates
+ explicit FieldVector (const K& t)
+ {
+ fill(t);
+ }
+
+ //! Constructor making vector with identical coordinates
+ FieldVector (const FieldVector & x) : _data(x._data)
+ {}
+
+ /**
+ * \brief Copy constructor from a second vector of possibly different type
+ *
+ * If the DenseVector type of the this constructor's argument
+ * is implemented by a FieldVector, it is statically checked
+ * if it has the correct size. If this is not the case
+ * the constructor is removed from the overload set using SFINAE.
+ *
+ * \param[in] x A DenseVector with correct size.
+ * \param[in] dummy A void* dummy argument needed by SFINAE.
+ */
+ template<class C>
+ FieldVector (const DenseVector<C> & x, typename Dune::enable_if<IsFieldVectorSizeCorrect<C,SIZE>::value>::type* dummy=0 )
+ {
+ DUNE_UNUSED_PARAMETER(dummy);
+ // do a run-time size check, for the case that x is not a FieldVector
+ assert(x.size() == SIZE);
+ for (size_type i = 0; i<SIZE; i++)
+ _data[i] = x[i];
+ }
+
+ //! Constructor making vector with identical coordinates
+ template<class K1, int SIZE1>
+ explicit FieldVector (const FieldVector<K1,SIZE1> & x)
+ {
+ dune_static_assert(SIZE1 == SIZE, "FieldVector in constructor has wrong size");
+ for (size_type i = 0; i<SIZE; i++)
+ _data[i] = x[i];
+ }
+ using Base::operator=;
+
+ DUNE_CONSTEXPR size_type size () const { return vec_size(); }
+
+ // make this thing a vector
+ DUNE_CONSTEXPR size_type vec_size () const { return SIZE; }
+ K & vec_access(size_type i) { return _data[i]; }
+ const K & vec_access(size_type i) const { return _data[i]; }
+ private:
+ void fill(const K& t)
+ {
+ for (int i=0; i<SIZE; i++) _data[i]=t;
+ }
+ };
+
+ /** \brief Read a FieldVector from an input stream
+ * \relates FieldVector
+ *
+ * \note This operator is STL compliant, i.e., the content of v is only
+ * changed if the read operation is successful.
+ *
+ * \param[in] in std :: istream to read from
+ * \param[out] v FieldVector to be read
+ *
+ * \returns the input stream (in)
+ */
+ template<class K, int SIZE>
+ inline std::istream &operator>> ( std::istream &in,
+ FieldVector<K, SIZE> &v )
+ {
+ FieldVector<K, SIZE> w;
+ for( typename FieldVector<K, SIZE>::size_type i = 0; i < SIZE; ++i )
+ in >> w[ i ];
+ if(in)
+ v = w;
+ return in;
+ }
+
+#ifndef DOXYGEN
+ template< class K >
+ struct DenseMatVecTraits< FieldVector<K,1> >
+ {
+ typedef FieldVector<K,1> derived_type;
+ typedef K container_type;
+ typedef K value_type;
+ typedef size_t size_type;
+ };
+
+ /** \brief Vectors containing only one component
+ */
+ template<class K>
+ class FieldVector<K, 1> :
+ public DenseVector< FieldVector<K,1> >
+ {
+ K _data;
+ typedef DenseVector< FieldVector<K,1> > Base;
+ public:
+ //! export size
+ enum {
+ //! The size of this vector.
+ dimension = 1
+ };
+
+ typedef typename Base::size_type size_type;
+
+ //===== construction
+
+ /** \brief Default constructor */
+ FieldVector ()
+ : _data()
+ {}
+
+ /** \brief Constructor with a given scalar */
+ FieldVector (const K& k) : _data(k) {}
+
+ //! Constructor making vector with identical coordinates
+ template<class C>
+ FieldVector (const DenseVector<C> & x)
+ {
+ dune_static_assert(((bool)IsFieldVectorSizeCorrect<C,1>::value), "FieldVectors do not match in dimension!");
+ assert(x.size() == 1);
+ _data = x[0];
+ }
+
+ //! copy constructor
+ FieldVector ( const FieldVector &other )
+ : _data( other._data )
+ {}
+
+ //! Assignment operator for scalar
+ inline FieldVector& operator= (const K& k)
+ {
+ _data = k;
+ return *this;
+ }
+
+ DUNE_CONSTEXPR size_type size () const { return vec_size(); }
+
+ //===== forward methods to container
+ DUNE_CONSTEXPR size_type vec_size () const { return 1; }
+ K & vec_access(size_type i)
+ {
+ assert(i == 0);
+ return _data;
+ }
+ const K & vec_access(size_type i) const
+ {
+ assert(i == 0);
+ return _data;
+ }
+
+ //===== conversion operator
+
+ /** \brief Conversion operator */
+ operator K () { return _data; }
+
+ /** \brief Const conversion operator */
+ operator K () const { return _data; }
+ };
+
+ /* ----- FV / FV ----- */
+ /* not necessary as these operations are already covered via the cast operator */
+
+ /* ----- FV / scalar ----- */
+
+ //! Binary addition, when using FieldVector<K,1> like K
+ template<class K>
+ inline FieldVector<K,1> operator+ (const FieldVector<K,1>& a, const K b)
+ {
+ return a[0]+b;
+ }
+
+ //! Binary subtraction, when using FieldVector<K,1> like K
+ template<class K>
+ inline FieldVector<K,1> operator- (const FieldVector<K,1>& a, const K b)
+ {
+ return a[0]-b;
+ }
+
+ //! Binary multiplication, when using FieldVector<K,1> like K
+ template<class K>
+ inline FieldVector<K,1> operator* (const FieldVector<K,1>& a, const K b)
+ {
+ return a[0]*b;
+ }
+
+ //! Binary division, when using FieldVector<K,1> like K
+ template<class K>
+ inline FieldVector<K,1> operator/ (const FieldVector<K,1>& a, const K b)
+ {
+ return a[0]/b;
+ }
+
+ //! Binary compare, when using FieldVector<K,1> like K
+ template<class K>
+ inline bool operator> (const FieldVector<K,1>& a, const K b)
+ {
+ return a[0]>b;
+ }
+
+ //! Binary compare, when using FieldVector<K,1> like K
+ template<class K>
+ inline bool operator>= (const FieldVector<K,1>& a, const K b)
+ {
+ return a[0]>=b;
+ }
+
+ //! Binary compare, when using FieldVector<K,1> like K
+ template<class K>
+ inline bool operator< (const FieldVector<K,1>& a, const K b)
+ {
+ return a[0]<b;
+ }
+
+ //! Binary compare, when using FieldVector<K,1> like K
+ template<class K>
+ inline bool operator<= (const FieldVector<K,1>& a, const K b)
+ {
+ return a[0]<=b;
+ }
+
+ //! Binary compare, when using FieldVector<K,1> like K
+ template<class K>
+ inline bool operator== (const FieldVector<K,1>& a, const K b)
+ {
+ return a[0]==b;
+ }
+
+ //! Binary compare, when using FieldVector<K,1> like K
+ template<class K>
+ inline bool operator!= (const FieldVector<K,1>& a, const K b)
+ {
+ return a[0]!=b;
+ }
+
+ /* ----- scalar / FV ------ */
+
+ //! Binary addition, when using FieldVector<K,1> like K
+ template<class K>
+ inline FieldVector<K,1> operator+ (const K a, const FieldVector<K,1>& b)
+ {
+ return a+b[0];
+ }
+
+ //! Binary subtraction, when using FieldVector<K,1> like K
+ template<class K>
+ inline FieldVector<K,1> operator- (const K a, const FieldVector<K,1>& b)
+ {
+ return a-b[0];
+ }
+
+ //! Binary multiplication, when using FieldVector<K,1> like K
+ template<class K>
+ inline FieldVector<K,1> operator* (const K a, const FieldVector<K,1>& b)
+ {
+ return a*b[0];
+ }
+
+ //! Binary division, when using FieldVector<K,1> like K
+ template<class K>
+ inline FieldVector<K,1> operator/ (const K a, const FieldVector<K,1>& b)
+ {
+ return a/b[0];
+ }
+
+ //! Binary compare, when using FieldVector<K,1> like K
+ template<class K>
+ inline bool operator> (const K a, const FieldVector<K,1>& b)
+ {
+ return a>b[0];
+ }
+
+ //! Binary compare, when using FieldVector<K,1> like K
+ template<class K>
+ inline bool operator>= (const K a, const FieldVector<K,1>& b)
+ {
+ return a>=b[0];
+ }
+
+ //! Binary compare, when using FieldVector<K,1> like K
+ template<class K>
+ inline bool operator< (const K a, const FieldVector<K,1>& b)
+ {
+ return a<b[0];
+ }
+
+ //! Binary compare, when using FieldVector<K,1> like K
+ template<class K>
+ inline bool operator<= (const K a, const FieldVector<K,1>& b)
+ {
+ return a<=b[0];
+ }
+
+ //! Binary compare, when using FieldVector<K,1> like K
+ template<class K>
+ inline bool operator== (const K a, const FieldVector<K,1>& b)
+ {
+ return a==b[0];
+ }
+
+ //! Binary compare, when using FieldVector<K,1> like K
+ template<class K>
+ inline bool operator!= (const K a, const FieldVector<K,1>& b)
+ {
+ return a!=b[0];
+ }
+#endif
+
+ /** @} end documentation */
+
+} // end namespace
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_GCD_HH
+#define DUNE_GCD_HH
+
+#include "static_assert.hh"
+namespace Dune
+{
+ /**
+ * @addtogroup Common
+ * @{
+ */
+ /**
+ * @file
+ * \brief Statically compute the greatest common divisor of two integers
+ */
+
+#ifndef DOXYGEN
+ /**
+ * @brief Helper for calculating the gcd.
+ */
+ template<long a, long b, bool bo>
+ struct GcdHelper
+ {};
+
+
+ template<long a, long b>
+ struct GcdHelper<a,b,true>
+ {
+ /**
+ * @brief Check that a>b.
+ */
+ static void conceptCheck()
+ {
+ dune_static_assert(b<a, "b<a must hold!");
+ dune_static_assert(0<b, "b must be positive");
+ }
+
+
+ /**
+ * @brief The greatest common divisor of the numbers a and b.
+ */
+ const static long gcd = GcdHelper<b,a%b,true>::gcd;
+ };
+
+ template<long a, long b>
+ struct GcdHelper<a,b,false>
+ {
+ /**
+ * @brief The greatest common divisor of the numbers a and b.
+ */
+ const static long gcd = GcdHelper<b,a,true>::gcd;
+ };
+ template<long a>
+ struct GcdHelper<a,0,true>
+ {
+ const static long gcd=a;
+ };
+
+#endif
+
+ /**
+ * @brief Calculator of the greatest common divisor.
+ */
+ template<long a, long b>
+ struct Gcd
+ {
+ /**
+ * @brief The greatest common divisior of a and b. */
+ const static long value = GcdHelper<a,b,(a>b)>::gcd;
+ };
+
+ /**
+ * @}
+ */
+}
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+#ifndef DUNE_GENERICITERATOR_HH
+#define DUNE_GENERICITERATOR_HH
+
+#include <dune/common/iteratorfacades.hh>
+#include <cassert>
+
+namespace Dune {
+
+ /*! \defgroup GenericIterator GenericIterator
+ \ingroup IteratorFacades
+
+ \brief Generic Iterator class for writing stl conformant iterators
+ for any container class with operator[]
+
+ Using this template class you can create an iterator and a const_iterator
+ for any container class.
+
+ Imagine you have SimpleContainer and would like to have an iterator.
+ All you have to do is provide operator[], begin() and end()
+ (for const and for non-const).
+
+ \code
+ template<class T>
+ class SimpleContainer{
+ public:
+ typedef GenericIterator<SimpleContainer<T>,T> iterator;
+
+ typedef GenericIterator<const SimpleContainer<T>,const T> const_iterator;
+
+ SimpleContainer(){
+ for(int i=0; i < 100; i++)
+ values_[i]=i;
+ }
+
+ iterator begin(){
+ return iterator(*this, 0);
+ }
+
+ const_iterator begin() const{
+ return const_iterator(*this, 0);
+ }
+
+ iterator end(){
+ return iterator(*this, 100);
+ }
+
+ const_iterator end() const{
+ return const_iterator(*this, 100);
+ }
+
+ T& operator[](int i){
+ return values_[i];
+ }
+
+ const T& operator[](int i) const{
+ return values_[i];
+ }
+ private:
+ T values_[100];
+ };
+ \endcode
+
+ See dune/common/test/iteratorfacestest.hh for details or
+ Dune::QuadratureDefault in dune/quadrature/quadrature.hh
+ for a real example.
+ */
+
+ /**
+ * @file
+ * @brief Implements a generic iterator class for writing stl conformant iterators.
+ *
+ * Using this generic iterator writing iterators for containers
+ * that implement operator[] is only a matter of seconds.
+ */
+
+ /**
+ \brief Get the 'const' version of a reference to a mutable object
+
+ Given a reference R=T& const_reference<R>::type gives you the typedef for const T&
+ */
+ template<class R>
+ struct const_reference
+ {
+ typedef const R type;
+ };
+
+ template<class R>
+ struct const_reference<const R>
+ {
+ typedef const R type;
+ };
+
+ template<class R>
+ struct const_reference<R&>
+ {
+ typedef const R& type;
+ };
+
+ template<class R>
+ struct const_reference<const R&>
+ {
+ typedef const R& type;
+ };
+
+ /**
+ \brief get the 'mutable' version of a reference to a const object
+
+ given a const reference R=const T& mutable_reference<R>::type gives you the typedef for T&
+ */
+ template<class R>
+ struct mutable_reference
+ {
+ typedef R type;
+ };
+
+ template<class R>
+ struct mutable_reference<const R>
+ {
+ typedef R type;
+ };
+
+ template<class R>
+ struct mutable_reference<R&>
+ {
+ typedef R& type;
+ };
+
+ template<class R>
+ struct mutable_reference<const R&>
+ {
+ typedef R& type;
+ };
+
+ /** @addtogroup GenericIterator
+ *
+ * @{
+ */
+
+ /**
+ * @brief Generic class for stl-conforming iterators for container classes with operator[].
+ *
+ * If template parameter C has a const qualifier we are a const iterator, otherwise we
+ * are a mutable iterator.
+ */
+ template<class C, class T, class R=T&, class D = std::ptrdiff_t,
+ template<class,class,class,class> class IteratorFacade=RandomAccessIteratorFacade>
+ class GenericIterator :
+ public IteratorFacade<GenericIterator<C,T,R,D,IteratorFacade>,T,R,D>
+ {
+ friend class GenericIterator<typename remove_const<C>::type, typename remove_const<T>::type, typename mutable_reference<R>::type, D, IteratorFacade>;
+ friend class GenericIterator<const typename remove_const<C>::type, const typename remove_const<T>::type, typename const_reference<R>::type, D, IteratorFacade>;
+
+ typedef GenericIterator<typename remove_const<C>::type, typename remove_const<T>::type, typename mutable_reference<R>::type, D, IteratorFacade> MutableIterator;
+ typedef GenericIterator<const typename remove_const<C>::type, const typename remove_const<T>::type, typename const_reference<R>::type, D, IteratorFacade> ConstIterator;
+
+ public:
+
+ /**
+ * @brief The type of container we are an iterator for.
+ *
+ * The container type must provide an operator[] method.
+ *
+ * If C has a const qualifier we are a const iterator, otherwise we
+ * are a mutable iterator.
+ */
+ typedef C Container;
+
+ /**
+ * @brief The value type of the iterator.
+ *
+ * This is the return type when dereferencing the iterator.
+ */
+ typedef T Value;
+
+ /**
+ * @brief The type of the difference between two positions.
+ */
+ typedef D DifferenceType;
+
+ /**
+ * @brief The type of the reference to the values accessed.
+ */
+ typedef R Reference;
+
+ // Constructors needed by the base iterators
+ GenericIterator() : container_(0), position_(0)
+ {}
+
+ /**
+ * @brief Constructor
+ * @param cont Reference to the container we are an iterator for
+ * @param pos The position the iterator will be positioned to
+ * (e.g. 0 for an iterator returned by Container::begin() or
+ * the size of the container for an iterator returned by Container::end()
+ */
+ GenericIterator(Container& cont, DifferenceType pos)
+ : container_(&cont), position_(pos)
+ {}
+
+ /**
+ * @brief Copy constructor
+ *
+ * This is somehow hard to understand, therefore play with the cases:
+ * 1. if we are mutable this is the only valid copy constructor, as the argument is a mutable iterator
+ * 2. if we are a const iterator the argument is a mutable iterator => This is the needed conversion to initialize a const iterator from a mutable one.
+ */
+ GenericIterator(const MutableIterator& other) : container_(other.container_), position_(other.position_)
+ {}
+
+ /**
+ * @brief Copy constructor
+ *
+ * @warning Calling this method results in a compiler error, if this is a mutable iterator.
+ *
+ * This is somehow hard to understand, therefore play with the cases:
+ * 1. if we are mutable the arguments is a const iterator and therefore calling this method is mistake in the user's code and results in a (probably not understandable) compiler error
+ * 2. If we are a const iterator this is the default copy constructor as the argument is a const iterator too.
+ */
+ GenericIterator(const ConstIterator& other) : container_(other.container_), position_(other.position_)
+ {}
+
+ // Methods needed by the forward iterator
+ bool equals(const MutableIterator & other) const
+ {
+ return position_ == other.position_ && container_ == other.container_;
+ }
+
+ bool equals(const ConstIterator & other) const
+ {
+ return position_ == other.position_ && container_ == other.container_;
+ }
+
+ Reference dereference() const {
+ return container_->operator[](position_);
+ }
+
+ void increment(){
+ ++position_;
+ }
+
+ // Additional function needed by BidirectionalIterator
+ void decrement(){
+ --position_;
+ }
+
+ // Additional function needed by RandomAccessIterator
+ Reference elementAt(DifferenceType i) const {
+ return container_->operator[](position_+i);
+ }
+
+ void advance(DifferenceType n){
+ position_=position_+n;
+ }
+
+ DifferenceType distanceTo(const MutableIterator& other) const
+ {
+ assert(other.container_==container_);
+ return other.position_ - position_;
+ }
+
+ DifferenceType distanceTo(const ConstIterator& other) const
+ {
+ assert(other.container_==container_);
+ return other.position_ - position_;
+ }
+
+ private:
+ Container *container_;
+ DifferenceType position_;
+ };
+
+ /** @} */
+
+} // end namespace Dune
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_GMPFIELD_HH
+#define DUNE_GMPFIELD_HH
+
+/** \file
+ * \brief Wrapper for the GNU multiprecision (GMP) library
+ */
+
+#include <iostream>
+
+#if HAVE_GMP
+
+#include <gmpxx.h>
+
+namespace Dune
+{
+
+ template< unsigned int precision >
+ class GMPField
+ : public mpf_class
+ {
+ typedef mpf_class Base;
+
+ public:
+ GMPField ()
+ : Base(0,precision)
+ {}
+
+ template< class T >
+ GMPField ( const T &v )
+ : Base( v,precision )
+ {}
+
+ /*
+ GMPField &operator=(const GMPField &other)
+ {
+ Base(*this) = Base(other);
+ return *this;
+ }
+ */
+
+ // type conversion operators
+ operator double () const
+ {
+ return this->get_d();
+ }
+
+ operator float () const
+ {
+ return this->get_d();
+ }
+ };
+
+
+
+ template< unsigned int precision >
+ inline GMPField< precision >
+ operator+ ( const GMPField< precision > &a, const GMPField< precision > &b )
+ {
+ typedef mpf_class F;
+ return ((const F &)a + (const F &)b);
+ }
+
+ template< unsigned int precision >
+ inline GMPField< precision >
+ operator- ( const GMPField< precision > &a, const GMPField< precision > &b )
+ {
+ typedef mpf_class F;
+ return ((const F &)a - (const F &)b);
+ }
+
+ template< unsigned int precision >
+ inline GMPField< precision >
+ operator- ( const GMPField< precision > &a )
+ {
+ typedef mpf_class F;
+ return -((const F &)a);
+ }
+
+ template< unsigned int precision >
+ inline GMPField< precision >
+ operator* ( const GMPField< precision > &a, const GMPField< precision > &b )
+ {
+ typedef mpf_class F;
+ return ((const F &)a * (const F &)b);
+ }
+
+ template< unsigned int precision >
+ inline GMPField< precision >
+ operator/ ( const GMPField< precision > &a, const GMPField< precision > &b )
+ {
+ typedef mpf_class F;
+ return ((const F &)a / (const F &)b);
+ }
+
+
+
+ template< unsigned int precision >
+ inline std::ostream &
+ operator<< ( std::ostream &out, const GMPField< precision > &value )
+ {
+ return out << static_cast<const mpf_class&>(value);
+ }
+
+}
+
+namespace std
+{
+
+ template< unsigned int precision >
+ inline Dune::GMPField< precision >
+ sqrt ( const Dune::GMPField< precision > &a )
+ {
+ return Dune::GMPField< precision >(sqrt(static_cast<const mpf_class&>(a)));
+ }
+
+ template< unsigned int precision >
+ inline Dune::GMPField< precision >
+ abs ( const Dune::GMPField< precision > &a )
+ {
+ return Dune::GMPField< precision >( abs( static_cast< const mpf_class & >( a ) ) );
+ }
+
+}
+
+#endif // HAVE_GMP
+
+#endif // #ifndef DUNE_GMPFIELD_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_COMMON_HASH_HH
+#define DUNE_COMMON_HASH_HH
+
+#include <dune/common/typetraits.hh>
+#include <dune/common/static_assert.hh>
+
+#if HAVE_STD_HASH
+#include <functional>
+#endif
+
+#if HAVE_TR1_HASH
+#include <tr1/functional>
+#endif
+
+#if HAVE_DUNE_BOOST
+
+#include <boost/version.hpp>
+
+// Boost 1.34.0 seems to be the first usable version of boost::functional::hash
+#if BOOST_VERSION >= 103400
+#define HAVE_BOOST_HASH 1
+
+// only pull in boost if really necessary
+#if !HAVE_STD_HASH && !HAVE_TR1_HASH
+
+#include <boost/functional/hash.hpp>
+
+#endif // !HAVE_STD_HASH && !HAVE_TR1_HASH
+#endif // BOOST_VERSION >= 103400
+#endif // HAVE_DUNE_BOOST
+
+/**
+ * \file
+ * \brief Support for calculating hash values of objects.
+ *
+ * This file provides the functor Dune::hash to calculate hash values and
+ * some infrastructure to simplify extending Dune::hash for user-defined types,
+ * independent of the actual underlying implementation.
+ *
+ */
+
+
+
+// ********************************************************************************
+// Doxygen documentation
+// ********************************************************************************
+
+#ifdef DOXYGEN
+
+namespace Dune {
+
+ //! Functor for hashing objects of type T.
+ /**
+ * The interface outlined below is compatible with std::hash, std::tr1::hash and
+ * boost::hash, so it is possible to use Dune::hash in associative containers from
+ * those libraries.
+ *
+ * The current implementation piggybacks on top of C++11, TR1 or Boost, in that order.
+ * As there is no local fallback implementation, hashing will not work without at least
+ * one of those dependencies installed.
+ */
+ template<typename T>
+ struct hash
+ {
+
+ //! Calculates the hash of t.
+ std::size_t operator()(const T& t) const
+ {
+ return hash(t);
+ }
+
+ };
+
+}
+
+//! Defines the required struct specialization to make type hashable via `Dune::hash`.
+/**
+ * In order to calculate the hash, operator() of the generated specialization will
+ * return the result of an unqualified call to the global function `hash_value(const type&)`.
+ * As the call is not qualified, the function will be found using argument-dependent lookup,
+ * allowing implementors to conveniently place it inside the class body.
+ *
+ * Consider the following type:
+ *
+ * \code
+ * namespace ns {
+ * template<typename A, int i>
+ * class Foo
+ * {
+ * ...
+ * };
+ * }
+ * \endcode
+ *
+ * In order to add support for `Dune::hash`, you need to extend the definition like this:
+ *
+ * \code
+ * namespace ns {
+ * template<typename A, int i>
+ * class Foo
+ * {
+ * ...
+ * // The keyword "friend" turns this into a global function that is a friend of Foo.
+ * inline friend std::size_t hash_value(const Foo& arg)
+ * {
+ * return ...;
+ * }
+ * };
+ * }
+ *
+ * // Define hash struct specialization
+ * DUNE_DEFINE_HASH(DUNE_HASH_TEMPLATE_ARGS(typename A, int i),DUNE_HASH_TYPE(Foo<A,i>))
+ * \endcode
+ *
+ * \warning
+ * As the specialization has to be placed in the original namespace of the
+ * `hash` struct (e.g. `std`), this macro *must* be called from the global namespace!
+ *
+ * \param template_args The template arguments required by the hash struct specialization,
+ * wrapped in a call to DUNE_HASH_TEMPLATE_ARGS. If this is a complete
+ * specialization, call DUNE_HASH_TEMPLATE_ARGS without arguments.
+ * \param type The exact type of the specialization, wrapped in a call to DUNE_HASH_TYPE.
+ */
+#define DUNE_DEFINE_HASH(template_args,type)
+
+
+//! Wrapper macro for the template arguments in DUNE_DEFINE_HASH.
+/**
+ * This macro should always be used as a wrapper for the template arguments when calling DUNE_DEFINE_HASH.
+ * It works around some preprocessor limitations when the template arguments contain commas or the list
+ * is completely empty.
+ */
+#define DUNE_HASH_TEMPLATE_ARGS(...)
+
+//! Wrapper macro for the type to be hashed in DUNE_DEFINE_HASH.
+/**
+ * This macro should always be used as a wrapper for the type of the specialization when calling
+ * DUNE_DEFINE_HASH.
+ * It works around some preprocessor limitations when the type contains commas.
+ */
+#define DUNE_HASH_TYPE(...)
+
+#else // DOXYGEN - hide all the ugly implementation
+
+
+
+// ********************************************************************************
+// C++11 support
+// ********************************************************************************
+
+#if HAVE_STD_HASH
+// We have std::hash from C++11
+
+// Announce that we provide Dune::hash
+#define HAVE_DUNE_HASH 1
+
+// import std::hash into Dune namespace
+namespace Dune {
+
+ using std::hash;
+
+}
+
+// Macro for defining a std::hash specialization for type.
+// This should not be called directly. Call DUNE_DEFINE_HASH
+// instead.
+#define DUNE_DEFINE_STD_HASH(template_args,type) \
+ namespace std { \
+ \
+ template<template_args> \
+ struct hash<type> \
+ { \
+ std::size_t operator()(const type& arg) const \
+ { \
+ return hash_value(arg); \
+ } \
+ }; \
+ \
+ } \
+
+#else // HAVE_STD_HASH
+
+// We do not support std::hash, so don't do anything here.
+#define DUNE_DEFINE_STD_HASH(template_args,type)
+
+#endif // HAVE_STD_HASH
+
+
+
+// ********************************************************************************
+// TR1 support
+// ********************************************************************************
+
+#if HAVE_TR1_HASH
+// We have std::tr1::hash from TR1
+
+#ifndef HAVE_DUNE_HASH
+// std::hash wasn't found, so use std::tr1::hash
+
+// Announce that we provide Dune::hash
+#define HAVE_DUNE_HASH 1
+
+// import std::tr1::hash into Dune namespace
+namespace Dune {
+
+ using std::tr1::hash;
+
+}
+
+#endif // HAVE_DUNE_HASH
+
+// Macro for defining a std::tr1::hash specialization for type.
+// This should not be called directly. Call DUNE_DEFINE_HASH
+// instead.
+#define DUNE_DEFINE_TR1_HASH(template_args,type) \
+ namespace std { \
+ namespace tr1 { \
+ \
+ template<template_args> \
+ struct hash<type> \
+ { \
+ std::size_t operator()(const type& arg) const \
+ { \
+ return hash_value(arg); \
+ } \
+ }; \
+ \
+ } \
+ } \
+
+#else // HAVE_TR1_HASH
+
+// We do not support std::tr1::hash, so don't do anything here.
+#define DUNE_DEFINE_TR1_HASH(template_args,type)
+
+#endif // HAVE_TR1_HASH
+
+
+
+// ********************************************************************************
+// common macros for both C++11 and TR1 support
+// ********************************************************************************
+
+#if HAVE_STD_HASH || HAVE_TR1_HASH
+
+// Wrapper macro for template arguments.
+// This is required because the template arguments can contain commas,
+// which will create a macro argument list of unknown length. That in itself
+// would not be a problem, but DUNE_DEFINE_HASH has to be called with two argument
+// lists of unknown length. So this macro wraps its arguments with parentheses,
+// turning it into a single argument. The result is used as the parameter list of
+// an expansion macro in the calls to the implementation-specific macros
+// for C++11 and TR1. Noto that technically, this trick is only legal for C++11,
+// but pretty much every compiler supports variadic macros in C++03 mode, as they
+// are part of C99.
+#define DUNE_HASH_TEMPLATE_ARGS(...) (__VA_ARGS__)
+
+// Wrapper macro for type to be hashed.
+// See above for rationale.
+#define DUNE_HASH_TYPE(...) (__VA_ARGS__)
+
+// Expansion macro for the parenthesed argument lists created by
+// DUNE_HASH_TEMPLATE_ARGS and DUNE_HASH_TYPE.
+#define DUNE_HASH_EXPAND_VA_ARGS(...) __VA_ARGS__
+
+// Define specializations for all discovered hash implementations.
+#define DUNE_DEFINE_HASH(template_args,type) \
+ DUNE_DEFINE_STD_HASH(DUNE_HASH_EXPAND_VA_ARGS template_args, DUNE_HASH_EXPAND_VA_ARGS type) \
+ DUNE_DEFINE_TR1_HASH(DUNE_HASH_EXPAND_VA_ARGS template_args,DUNE_HASH_EXPAND_VA_ARGS type) \
+
+
+#else // HAVE_STD_HASH || HAVE_TR1_HASH
+
+
+// Fallback implementation that doesn't do anything.
+#define DUNE_DEFINE_HASH(template_args,type)
+
+// Consider DUNE_HASH_TEMPLATE_ARGS as an argument-less macro and
+// replace it with an empty token.
+// This will leave its arguments in parentheses, causing them
+// to be considered as a single argument to DUNE_DEFINE_HASH, which
+// will ignore them anyway.
+#define DUNE_HASH_TEMPLATE_ARGS
+
+// Replace DUNE_HASH_TYPE with an empty token. See above for rationale.
+#define DUNE_HASH_TYPE
+
+#endif // HAVE_STD_HASH || HAVE_TR1_HASH
+
+
+
+// ********************************************************************************
+// Boost support
+// ********************************************************************************
+
+#if !HAVE_DUNE_HASH && HAVE_BOOST_HASH
+// We haven't found a hash implementation yet and Boost is available
+
+// Announce that we provide Dune::hash
+#define HAVE_DUNE_HASH 1
+
+// import boost::hash into Dune namespace
+namespace Dune {
+
+ using boost::hash;
+
+}
+
+// We no not need to register our types with boost::hash, as its extension
+// mechanism will automatically pick up the global hash_value() functions.
+
+#endif // !HAVE_DUNE_HASH && HAVE_BOOST_HASH
+
+#endif // DOXYGEN
+
+
+
+// ********************************************************************************
+// Some utility functions for combining hashes of member variables.
+// ********************************************************************************
+
+#if HAVE_DUNE_HASH || defined(DOXYGEN)
+
+namespace Dune {
+
+ // The following functions are an implementation of the proposed hash extensions for
+ // the C++ standard by Peter Dimov
+ // (cf. http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf, issue 6.18).
+ // They are also contained in the boost::functional::hash library by Daniel James, but
+ // that implementation uses boost::hash internally, while we want to use Dune::hash. They
+ // are also considered for inclusion in TR2 (then based on std::hash, of course).
+
+#ifndef DOXYGEN
+
+ // helper struct for providing different hash combining algorithms dependent on
+ // the size of size_t.
+ // hash_combiner has to be specialized for the size (in bytes) of std::size_t.
+ // Specialized versions should provide a method
+ //
+ // template <typename typeof_size_t, typename T>
+ // void operator()(typeof_size_t& seed, const T& arg) const;
+ //
+ // that will be called by the interface function hash_combine() described further below.
+ // The redundant template parameter typeof_size_t is needed to avoid warnings for the
+ // unused 64-bit specialization on 32-bit systems.
+ //
+ // There is no default implementation!
+ template<int sizeof_size_t>
+ struct hash_combiner;
+
+
+ // hash combining for 64-bit platforms.
+ template<>
+ struct hash_combiner<8>
+ {
+
+ template<typename typeof_size_t, typename T>
+ void operator()(typeof_size_t& seed, const T& arg) const
+ {
+ dune_static_assert(sizeof(typeof_size_t)==8, "hash_combiner::operator() instantiated with nonmatching type and size");
+
+ // The following algorithm for combining two 64-bit hash values is inspired by a similar
+ // function in CityHash (http://cityhash.googlecode.com/svn-history/r2/trunk/src/city.h),
+ // which is in turn based on ideas from the MurmurHash library. The basic idea is easy to
+ // grasp, though: New information is XORed into the existing hash multiple times at different
+ // places (using shift operations), and the resulting pattern is spread over the complete
+ // range of available bits via multiplication with a "magic" constant. The constants used
+ // below (47 and 0x9ddfea08eb382d69ULL) are taken from the CityHash implementation.
+ //
+ // We opted not to use the mixing algorithm proposed in the C++ working group defect list at
+ // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf, p. 57f. because it
+ // has very bad hash distribution properties if you apply it to lists of very small numbers,
+ // an application that is frequent in PDELab's ordering framework.
+
+ Dune::hash<T> hasher;
+ const typeof_size_t kMul = 0x9ddfea08eb382d69ULL;
+ typeof_size_t h = hasher(arg);
+ typeof_size_t a = (seed ^ h) * kMul;
+ a ^= (a >> 47);
+ typeof_size_t b = (h ^ a) * kMul;
+ b ^= (b >> 47);
+ b *= kMul;
+ seed = b;
+ }
+
+ };
+
+
+ // hash combining for 32-bit platforms.
+ template<>
+ struct hash_combiner<4>
+ {
+
+ template<typename typeof_size_t, typename T>
+ void operator()(typeof_size_t& seed, const T& arg) const
+ {
+ dune_static_assert(sizeof(typeof_size_t)==4, "hash_combiner::operator() instantiated with nonmatching type and size");
+
+ // The default algorithm above requires a 64-bit std::size_t. The following algorithm is a
+ // 32-bit compatible fallback, again inspired by CityHash and MurmurHash
+ // (http://cityhash.googlecode.com/svn-history/r2/trunk/src/city.cc).
+ // It uses 32-bit constants and relies on rotation instead of multiplication to spread the
+ // mixed bits as that is apparently more efficient on IA-32. The constants used below are again
+ // taken from CityHash, in particular from the file referenced above.
+
+ Dune::hash<T> hasher;
+ const typeof_size_t c1 = 0xcc9e2d51;
+ const typeof_size_t c2 = 0x1b873593;
+ const typeof_size_t c3 = 0xe6546b64;
+ typeof_size_t h = hasher(arg);
+ typeof_size_t a = seed * c1;
+ a = (a >> 17) | (a << (32 - 17));
+ a *= c2;
+ h ^= a;
+ h = (h >> 19) | (h << (32 - 19));
+ seed = h * 5 + c3;
+ }
+
+ };
+
+#endif // DOXYGEN
+
+ //! Calculates the hash value of arg and combines it in-place with seed.
+ /**
+ * \note This function is only available if the macro `HAVE_DUNE_HASH` is defined.
+ *
+ * \param seed The hash value that will be combined with the hash of arg.
+ * \param arg The object for which to calculate a hash value and combine it with seed.
+ */
+ template<typename T>
+ inline void hash_combine(std::size_t& seed, const T& arg)
+ {
+ hash_combiner<sizeof(std::size_t)>()(seed,arg);
+ }
+
+ //! Hashes all elements in the range [first,last) and returns the combined hash.
+ /**
+ * \note This function is only available if the macro `HAVE_DUNE_HASH` is defined.
+ *
+ * \param first Iterator pointing to the first object to hash.
+ * \param last Iterator pointing one past the last object to hash.
+
+ * \returns The result of hashing all objects in the range and combining them
+ * using hash_combine() in sequential fashion, starting with seed 0.
+ */
+ template<typename It>
+ inline std::size_t hash_range(It first, It last)
+ {
+ std::size_t seed = 0;
+ for (; first != last; ++first)
+ {
+ hash_combine(seed,*first);
+ }
+ return seed;
+ }
+
+ //! Hashes all elements in the range [first,last) and combines the hashes in-place with seed.
+ /**
+ * \note This function is only available if the macro `HAVE_DUNE_HASH` is defined.
+ *
+ * \param seed Start value that will be combined with the hash values of all objects in
+ * the range using hash_combine() in sequential fashion.
+ * \param first Iterator pointing to the first ojbect to hash.
+ * \param last Iterator pointing one past the last object to hash.
+ */
+ template<typename It>
+ inline void hash_range(std::size_t& seed, It first, It last)
+ {
+ for (; first != last; ++first)
+ {
+ hash_combine(seed,*first);
+ }
+ }
+
+} // end namespace Dune
+
+#endif // HAVE_DUNE_HASH || defined(DOXYGEN)
+
+#endif // DUNE_COMMON_HASH_HH
--- /dev/null
+#ifndef DUNE_COMMON_IDENTITYMATRIX_HH
+#define DUNE_COMMON_IDENTITYMATRIX_HH
+
+#include <dune/common/fmatrix.hh>
+#include <dune/common/ftraits.hh>
+#include <dune/common/math.hh>
+#include <dune/common/std/constexpr.hh>
+
+/**
+ * \file
+ * \ingroup DenseMatVec
+ * \brief Implementation of an identity matrix that does not store
+ * any data.
+ * \author Christoph Gersbacher
+ */
+
+namespace Dune
+{
+
+ // IdentityMatrix
+ // --------------
+
+ /** \class IdentityMatrix
+ *
+ * \ingroup DenseMatVec
+ *
+ * \brief Read-only identity matrix.
+ *
+ * Implementation of an identity matrix that does not store any data.
+ *
+ * \tparam K field type
+ * \tparam N dimension
+ */
+ template< class K, int N >
+ struct IdentityMatrix
+ {
+ /** \brief field type */
+ typedef K field_type;
+ /** \brief size type */
+ typedef std::size_t size_type;
+
+ /** \brief return number of rows */
+ DUNE_CONSTEXPR size_type rows () const { return N; }
+ /** \brief return number of columns */
+ DUNE_CONSTEXPR size_type cols () const { return N; }
+
+ /** \copydoc Dune::DenseMatrix::mv */
+ template< class X, class Y >
+ void mv ( const X &x, Y &y ) const
+ {
+ y = x;
+ }
+
+ /** \copydoc Dune::DenseMatrix::mtv */
+ template< class X, class Y >
+ void mtv ( const X &x, Y &y ) const
+ {
+ y = x;
+ }
+
+ /** \copydoc Dune::DenseMatrix::umv */
+ template< class X, class Y >
+ void umv ( const X &x, Y &y ) const
+ {
+ y += x;
+ }
+
+ /** \copydoc Dune::DenseMatrix::umtv */
+ template< class X, class Y >
+ void umtv ( const X &x, Y &y ) const
+ {
+ y += x;
+ }
+
+ /** \copydoc Dune::DenseMatrix::umhv */
+ template< class X, class Y >
+ void umhv ( const X &x, Y &y ) const
+ {
+ y += x;
+ }
+
+ /** \copydoc Dune::DenseMatrix::mmv */
+ template< class X, class Y >
+ void mmv ( const X &x, Y &y ) const
+ {
+ y -= x;
+ }
+
+ /** \copydoc Dune::DenseMatrix::mmtv */
+ template< class X, class Y >
+ void mmtv ( const X &x, Y &y ) const
+ {
+ y -= x;
+ }
+
+ /** \copydoc Dune::DenseMatrix::mmhv */
+ template< class X, class Y >
+ void mmhv ( const X &x, Y &y ) const
+ {
+ y -= x;
+ }
+
+ /** \copydoc Dune::DenseMatrix::usmv */
+ template< class X, class Y >
+ void usmv ( const field_type &alpha, const X &x, Y &y ) const
+ {
+ y.axpy( alpha, x );
+ }
+
+ /** \copydoc Dune::DenseMatrix::usmtv */
+ template< class X, class Y >
+ void usmtv ( const field_type &alpha, const X &x, Y &y ) const
+ {
+ y.axpy( alpha, x );
+ }
+
+ /** \copydoc Dune::DenseMatrix::usmhv */
+ template< class X, class Y >
+ void usmhv ( const field_type &alpha, const X &x, Y &y ) const
+ {
+ y.axpy( alpha, x );
+ }
+
+ /** \copydoc Dune::DenseMatrix::frobenius_norm */
+ typename FieldTraits< field_type >::real_type frobenius_norm () const
+ {
+ return std::sqrt( frobenius_norm2() );
+ }
+
+ /** \copydoc Dune::DenseMatrix::frobenius_norm2 */
+ typename FieldTraits< field_type >::real_type frobenius_norm2 () const
+ {
+ return FieldTraits< field_type >::real_type( N );
+ }
+
+ /** \copydoc Dune::DenseMatrix::infinity_norm */
+ typename FieldTraits< field_type >::real_type infinity_norm () const
+ {
+ return FieldTraits< field_type >::real_type( 1 );
+ }
+
+ /** \copydoc Dune::DenseMatrix::infinity_norm_real */
+ typename FieldTraits< field_type >::real_type infinity_norm_real () const
+ {
+ return FieldTraits< field_type >::real_type( 1 );
+ }
+
+ /** \brief cast to FieldMatrix */
+ operator FieldMatrix< field_type, N, N > () const
+ {
+ FieldMatrix< field_type, N, N > fieldMatrix( 0 );
+ for( int i = 0; i < N; ++i )
+ fieldMatrix[ i ][ i ] = field_type( 1 );
+ return fieldMatrix;
+ }
+ };
+
+} // namespace Dune
+
+#endif // #ifndef DUNE_COMMON_IDENTITYMATRIX_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_COMMON_INDENT_HH
+#define DUNE_COMMON_INDENT_HH
+
+#include <ostream>
+#include <string>
+
+namespace Dune {
+ /** @addtogroup Common
+ *
+ * @{
+ */
+ /**
+ * @file
+ * @brief Utility class for handling nested indentation in output.
+ * @author Jö Fahlke
+ */
+ //! Utility class for handling nested indentation in output.
+ /**
+ * An indentation object hast a string basic_indent and an indentation
+ * level. When it is put into a std::ostream using << it will print its
+ * basic_indent as many times as its indentation level. By default the
+ * basic_indent will be two spaces and the indentation level will be 0.
+ *
+ * An Indent object may also have a reference to a parent Indent object. If
+ * it has, that object it put into the stream with the << operator before
+ * the indentation of this object is put into the stream. This effectively
+ * chains Indent objects together.
+ *
+ * You can use the ++ operator to raise and the -- operator to lower the
+ * indentation by one level.
+ *
+ * You can use the + operator with a numeric second argument morelevel to
+ * create a copy of the Indent object with the indentation level increased
+ * morelevel times. This is mainly useful to pass indent+1 to a function,
+ * where indent is an indentation object.
+ *
+ * You can use the + operator with a string second argument newindent to
+ * create a new Indent object with this object as parent, a basic_indent of
+ * newindent, and an indentation level of one. This is mainly useful to
+ * pass indent+"> " to a function, where "> " is a possibly different
+ * indentation string then the one used by indent indentation object.
+ *
+ * \note The idea is for functions receive indentation objects as call by
+ * value parameters. This way, the indentation object of the caller
+ * will not be modified by the function and the function can simply
+ * return at anytime without having to clean up.
+ */
+ class Indent
+ {
+ const Indent* parent;
+ std::string basic_indent;
+ unsigned level;
+
+ public:
+ //! setup without parent
+ /**
+ * \note Initial indentation level is 0 by default for this constructor.
+ */
+ inline Indent(const std::string& basic_indent_ = " ", unsigned level_ = 0)
+ : parent(0), basic_indent(basic_indent_), level(level_)
+ { }
+
+ //! setup without parent and basic_indentation of two spaces
+ inline Indent(unsigned level_)
+ : parent(0), basic_indent(" "), level(level_)
+ { }
+
+ //! setup with parent
+ /**
+ * \note Initial indentation level is 1 by default for this constructor.
+ */
+ inline Indent(const Indent* parent_,
+ const std::string& basic_indent_ = " ", unsigned level_ = 1)
+ : parent(parent_), basic_indent(basic_indent_), level(level_)
+ { }
+
+ //! setup with parent
+ inline Indent(const Indent* parent_, unsigned level_)
+ : parent(parent_), basic_indent(" "), level(level_)
+ { }
+
+ //! create new indentation object with this one as parent
+ inline Indent operator+(const std::string& newindent) const {
+ return Indent(this, newindent);
+ }
+ //! create a copy of this indetation object with raised level
+ inline Indent operator+(unsigned morelevel) const {
+ return Indent(parent, basic_indent, level+morelevel);
+ }
+ //! raise indentation level
+ inline Indent& operator++() { ++level; return *this; }
+ //! lower indentation level
+ inline Indent& operator--() { --level; return *this; }
+
+ //! write indentation to a stream
+ friend inline std::ostream& operator<<(std::ostream& s,
+ const Indent& indent);
+ };
+
+ //! write indentation to a stream
+ inline std::ostream& operator<<(std::ostream& s, const Indent& indent) {
+ if(indent.parent)
+ s << *indent.parent;
+ for(unsigned i = 0; i < indent.level; ++i)
+ s << indent.basic_indent;
+ return s;
+ }
+
+ /** }@ group Common */
+
+} // namespace Dune
+
+#endif // DUNE_COMMON_INDENT_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_INTERFACES_HH
+#define DUNE_INTERFACES_HH
+
+/** @file
+ @author Robert Kloefkorn
+ @brief Provides interfaces for detection of specific behavior
+ */
+
+namespace Dune {
+
+ //! An interface class for cloneable objects
+ struct Cloneable {
+
+ /** \brief Clones the object
+ * clone needs to be redefined by an implementation class, with the
+ * return type covariantly adapted. Remember to
+ * delete the resulting pointer.
+ */
+ virtual Cloneable* clone() const = 0;
+
+ /** \brief Destructor */
+ virtual ~Cloneable()
+ {}
+
+ };
+
+} // end namespace Dune
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <dune/common/ios_state.hh>
+
+namespace Dune {
+
+ //////////////////////////////////////////////////////////////////////
+ //
+ // class ios_base_all_saver
+ //
+
+ ios_base_all_saver::ios_base_all_saver(state_type& ios_)
+ : ios(ios_), oldflags(ios.flags()), oldprec(ios.precision()),
+ oldwidth(ios.width())
+ {}
+
+ ios_base_all_saver::~ios_base_all_saver()
+ {
+ restore();
+ }
+
+ void ios_base_all_saver::restore()
+ {
+ ios.flags(oldflags);
+ ios.precision(oldprec);
+ ios.width(oldwidth);
+ }
+
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_COMMON_IOS_STATE_HH
+#define DUNE_COMMON_IOS_STATE_HH
+
+#include <ios>
+
+namespace Dune {
+ /** @addtogroup Common
+ *
+ * @{
+ */
+ /**
+ * @file
+ * @brief Utility class for storing and resetting stream attributes.
+ * @author Markus Blatt
+ */
+ /**
+ * @brief Utility class for storing and resetting stream attributes.
+ *
+ * The constructor saves the attributes currently set in the ios_base
+ * object and the destructor restores these attributes again. The
+ * attributes can also be restores at any time by calling the method
+ * restore().
+ *
+ * The saved attributes are the format flags, precision, and width.
+ *
+ * @note The interface of this class is meant to be drop-in compatible the
+ * the class of the same name from <boost/io/ios_state.hpp>.
+ */
+ class ios_base_all_saver
+ {
+ public:
+ /** @brief Export type of object we save the state for */
+ typedef std::ios_base state_type;
+
+ /**
+ * @brief Constructor that stores the currently used flags.
+ * @param ios_ The ios_base object whose flags are to be saved and
+ * restored. Any stream object should work here.
+ *
+ * @note A reference to the ios_base object is store in this object. Thus
+ * the ios_base object must remain valid until the destructor of
+ * this object has been called.
+ */
+ ios_base_all_saver(state_type& ios_);
+
+ /**
+ * @brief Destructor that restores the flags stored by the constructor.
+ */
+ ~ios_base_all_saver();
+
+ /**
+ * @brief Restore flags now
+ *
+ * The flags will also be restored at destruction time even if this method
+ * was used.
+ */
+ void restore();
+
+ private:
+ /** @brief the ios object to restore the flags to. */
+ state_type& ios;
+ /** @brief The flags used when the constructor was called. */
+ state_type::fmtflags oldflags;
+ /** @brief The precision in use when the constructor was called. */
+ std::streamsize oldprec;
+ /** @brief The width in use when the constructor was called. */
+ std::streamsize oldwidth;
+ };
+
+ /** }@ */
+}
+
+#endif // DUNE_COMMON_IOS_STATE_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+#ifndef DUNE_ITERATORFACADES_HH
+#define DUNE_ITERATORFACADES_HH
+#include <iterator>
+#include "typetraits.hh"
+
+namespace Dune
+{
+ /*! \defgroup IteratorFacades Iterator facades
+ \ingroup Common
+
+ \brief Iterator facades for writing stl conformant iterators.
+
+ With using these facades writing iterators for arbitrary containers becomes much less
+ cumbersome as only few functions have to be implemented. All other functions needed by
+ the stl are provided by the facades using the Barton-Nackman trick (also known as
+ curiously recurring template pattern).
+
+ The following example illustrates how a random access iterator might be written:
+
+ \code
+ #include<dune/common/iteratorfacades.hh>
+
+ ...
+
+ template<class C, class T>
+ class TestIterator : public Dune::BidirectionalIteratorFacade<TestIterator<C,T>,T, T&, int>
+ {
+ friend class TestIterator<typename remove_const<C>::type, typename remove_const<T>::type >;
+ friend class TestIterator<const typename remove_const<C>::type, const typename remove_const<T>::type >;
+
+ public:
+
+ // Constructors needed by the facade iterators.
+ TestIterator(): container_(0), position_(0)
+ { }
+
+ TestIterator(C& cont, int pos)
+ : container_(&cont), position_(pos)
+ {}
+
+ TestIterator(const TestIterator<typename remove_const<C>::type, typename remove_const<T>::type >& other)
+ : container_(other.container_), position_(other.position_)
+ {}
+
+
+ TestIterator(const TestIterator<const typename remove_const<C>::type, const typename remove_const<T>::type >& other)
+ : container_(other.container_), position_(other.position_)
+ {}
+
+ // Methods needed by the forward iterator
+ bool equals(const TestIterator<typename remove_const<C>::type,typename remove_const<T>::type>& other) const
+ {
+ return position_ == other.position_ && container_ == other.container_;
+ }
+
+
+ bool equals(const TestIterator<const typename remove_const<C>::type,const typename remove_const<T>::type>& other) const
+ {
+ return position_ == other.position_ && container_ == other.container_;
+ }
+
+ T& dereference() const
+ {
+ return container_->values_[position_];
+ }
+
+ void increment()
+ {
+ ++position_;
+ }
+
+ // Additional function needed by BidirectionalIterator
+ void decrement()
+ {
+ --position_;
+ }
+
+ // Additional function needed by RandomAccessIterator
+ T& elementAt(int i)const
+ {
+ return container_->operator[](position_+i);
+ }
+
+ void advance(int n)
+ {
+ position_=position_+n;
+ }
+
+ std::ptrdiff_t distanceTo(TestIterator<const typename remove_const<C>::type,const typename remove_const<T>::type> other) const
+ {
+ assert(other.container_==container_);
+ return other.position_ - position_;
+ }
+
+ std::ptrdiff_t distanceTo(TestIterator<const typename remove_const<C>::type, typename remove_const<T>::type> other) const
+ {
+ assert(other.container_==container_);
+ return other.position_ - position_;
+ }
+ private:
+ C *container_;
+ size_t position_;
+ };
+
+ \endcode
+ See dune/common/test/iteratorbase.hh for details.
+ */
+
+
+ /**
+ * @file
+ * @brief This file implements iterator facade classes for writing stl conformant iterators.
+ *
+ * With using these facades writing iterators for arbitrary containers becomes much less
+ * cumbersome as only few functions have to be implemented. All other functions needed by
+ * the stl are provided by the facades using the Barton-Nackman trick (also known as
+ * curiously recurring template pattern.
+ */
+
+ /** @addtogroup IteratorFacades
+ *
+ * @{
+ */
+ /**
+ * @brief Base class for stl conformant forward iterators.
+ *
+ * \tparam T The derived class
+ * \tparam V The value type
+ * \tparam R The reference type
+ * \tparam D The type for differences between two iterators
+ */
+ template<class T, class V, class R = V&, class D = std::ptrdiff_t>
+ class ForwardIteratorFacade :
+ public std::iterator< std::forward_iterator_tag,
+ typename remove_const<V>::type, // std::iterator needs mutable value type
+ D,
+ V*,
+ R>
+ {
+
+ public:
+ /**
+ * @brief The type of derived iterator.
+ *
+ * The iterator has to define following
+ * functions have to be present:
+ *
+ * \code
+ *
+ * // Access the value referred to.
+ * Reference dereference() const;
+ *
+ * // Compare for equality with iterator j
+ * bool equals(j);
+ *
+ * // position the iterator at the next element.
+ * void increment()
+ *
+ * // check for equality with other iterator
+ * bool equals(other)
+ * \endcode
+ *
+ * For an elaborate explanation see the
+ * <A HREF="http://www.sgi.com/tech/stl/iterator_traits.html">STL Documentation</A>!
+ */
+ typedef T DerivedType;
+
+ /**
+ * @brief The type of value accessed through the iterator.
+ */
+ typedef V Value;
+
+ /**
+ * @brief The pointer to the Value.
+ */
+ typedef V* Pointer;
+
+ /**
+ * @brief The type of the difference between two positions.
+ */
+ typedef D DifferenceType;
+
+ /**
+ * @brief The type of the reference to the values accessed.
+ */
+ typedef R Reference;
+
+ /** @brief Dereferencing operator. */
+ Reference operator*() const
+ {
+ return static_cast<DerivedType const*>(this)->dereference();
+ }
+
+ Pointer operator->() const
+ {
+ return &(static_cast<const DerivedType *>(this)->dereference());
+ }
+
+ /** @brief Preincrement operator. */
+ DerivedType& operator++()
+ {
+ static_cast<DerivedType *>(this)->increment();
+ return *static_cast<DerivedType *>(this);
+ }
+
+ /** @brief Postincrement operator. */
+ DerivedType operator++(int)
+ {
+ DerivedType tmp(static_cast<DerivedType const&>(*this));
+ this->operator++();
+ return tmp;
+ }
+ };
+
+ /**
+ * @brief Checks for equality.
+ *
+ * This operation is only defined if either D2
+ * is convertible to D1 or vice versa. If that is
+ * not the case the compiler will report an error
+ * as EnableIfInterOperable<D1,D2,bool>::type is
+ * not defined.
+ *
+ */
+ template<class T1, class V1, class R1, class D,
+ class T2, class V2, class R2>
+ inline typename EnableIfInterOperable<T1,T2,bool>::type
+ operator==(const ForwardIteratorFacade<T1,V1,R1,D>& lhs,
+ const ForwardIteratorFacade<T2,V2,R2,D>& rhs)
+ {
+ if(Conversion<T2,T1>::exists)
+ return static_cast<const T1&>(lhs).equals(static_cast<const T2&>(rhs));
+ else
+ return static_cast<const T2&>(rhs).equals(static_cast<const T1&>(lhs));
+ }
+
+ /**
+ * @brief Checks for inequality.
+ *
+ * This operation is only defined if either D2
+ * is convertible to D1 or vice versa. If that is
+ * not the case the compiler will report an error
+ * as EnableIfInterOperable<D1,D2,bool>::type is
+ * not defined.
+ *
+ */
+ template<class T1, class V1, class R1, class D,
+ class T2, class V2, class R2>
+ inline typename EnableIfInterOperable<T1,T2,bool>::type
+ operator!=(const ForwardIteratorFacade<T1,V1,R1,D>& lhs,
+ const ForwardIteratorFacade<T2,V2,R2,D>& rhs)
+ {
+ if(Conversion<T2,T1>::exists)
+ return !static_cast<const T1&>(lhs).equals(static_cast<const T2&>(rhs));
+ else
+ return !static_cast<const T2&>(rhs).equals(static_cast<const T1&>(lhs));
+ }
+
+ /**
+ * @brief Facade class for stl conformant bidirectional iterators.
+ *
+ */
+ template<class T, class V, class R = V&, class D = std::ptrdiff_t>
+ class BidirectionalIteratorFacade :
+ public std::iterator< std::bidirectional_iterator_tag,
+ typename remove_const<V>::type, // std::iterator needs mutable value type
+ D,
+ V*,
+ R>
+ {
+
+ public:
+ /**
+ * @brief The type of derived iterator.
+ *
+ * The iterator has to define following
+ * functions have to be present:
+ *
+ * \code
+ *
+ * // Access the value referred to.
+ * Reference dereference() const;
+ *
+ * // Compare for equality with j
+ * bool equals(j);
+ *
+ * // position the iterator at the next element.
+ * void increment()
+ *
+ * // position the iterator at the previous element.
+ * void decrement()
+ *
+ * \endcode
+ *
+ * For an elaborate explanation see the
+ * <A HREF="http://www.sgi.com/tech/stl/iterator_traits.html">STL Documentation</A>
+ */
+ typedef T DerivedType;
+
+ /**
+ * @brief The type of value accessed through the iterator.
+ */
+ typedef V Value;
+
+ /**
+ * @brief The pointer to the Value.
+ */
+ typedef V* Pointer;
+
+ /**
+ * @brief The type of the difference between two positions.
+ */
+ typedef D DifferenceType;
+
+ /**
+ * @brief The type of the reference to the values accessed.
+ */
+ typedef R Reference;
+
+ /** @brief Dereferencing operator. */
+ Reference operator*() const
+ {
+ return static_cast<DerivedType const*>(this)->dereference();
+ }
+
+ Pointer operator->() const
+ {
+ return &(static_cast<const DerivedType *>(this)->dereference());
+ }
+
+ /** @brief Preincrement operator. */
+ DerivedType& operator++()
+ {
+ static_cast<DerivedType *>(this)->increment();
+ return *static_cast<DerivedType *>(this);
+ }
+
+ /** @brief Postincrement operator. */
+ DerivedType operator++(int)
+ {
+ DerivedType tmp(static_cast<DerivedType const&>(*this));
+ this->operator++();
+ return tmp;
+ }
+
+
+ /** @brief Preincrement operator. */
+ DerivedType& operator--()
+ {
+ static_cast<DerivedType *>(this)->decrement();
+ return *static_cast<DerivedType *>(this);
+ }
+
+ /** @brief Postincrement operator. */
+ DerivedType operator--(int)
+ {
+ DerivedType tmp(static_cast<DerivedType const&>(*this));
+ this->operator--();
+ return tmp;
+ }
+ };
+
+ /**
+ * @brief Checks for equality.
+ *
+ * This operation is only defined if T2 is convertible to T1, otherwise it
+ * is removed from the overload set since the enable_if for the return type
+ * yield an invalid type expression.
+ */
+ template<class T1, class V1, class R1, class D,
+ class T2, class V2, class R2>
+ inline typename enable_if<Conversion<T2,T1>::exists,bool>::type
+ operator==(const BidirectionalIteratorFacade<T1,V1,R1,D>& lhs,
+ const BidirectionalIteratorFacade<T2,V2,R2,D>& rhs)
+ {
+ return static_cast<const T1&>(lhs).equals(static_cast<const T2&>(rhs));
+ }
+
+ /**
+ * @brief Checks for equality.
+ *
+ * This operation is only defined if either T1 is convertible to T2, and T2
+ * is not convetible to T1. Otherwise the operator is removed from the
+ * overload set since the enable_if for the return type yield an invalid
+ * type expression.
+ */
+ template<class T1, class V1, class R1, class D,
+ class T2, class V2, class R2>
+ inline
+ typename enable_if<Conversion<T1,T2>::exists && !Conversion<T2,T1>::exists,
+ bool>::type
+ operator==(const BidirectionalIteratorFacade<T1,V1,R1,D>& lhs,
+ const BidirectionalIteratorFacade<T2,V2,R2,D>& rhs)
+ {
+ return static_cast<const T2&>(rhs).equals(static_cast<const T1&>(lhs));
+ }
+
+ /**
+ * @brief Checks for inequality.
+ *
+ * This operation is only defined if either D2
+ * is convertible to D1 or vice versa. If that is
+ * not the case the compiler will report an error
+ * as EnableIfInterOperable<D1,D2,bool>::type is
+ * not defined.
+ *
+ */
+ template<class T1, class V1, class R1, class D,
+ class T2, class V2, class R2>
+ inline typename EnableIfInterOperable<T1,T2,bool>::type
+ operator!=(const BidirectionalIteratorFacade<T1,V1,R1,D>& lhs,
+ const BidirectionalIteratorFacade<T2,V2,R2,D>& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+ /**
+ * @brief Base class for stl conformant forward iterators.
+ *
+ */
+ template<class T, class V, class R = V&, class D = std::ptrdiff_t>
+ class RandomAccessIteratorFacade :
+ public std::iterator< std::random_access_iterator_tag,
+ typename remove_const<V>::type, // std::iterator needs mutable value type
+ D,
+ V*,
+ R>
+ {
+
+ public:
+ /**
+ * @brief The type of derived iterator.
+ *
+ * The iterator has to define following
+ * functions have to be present:
+ *
+ * \code
+ *
+ * // Access the value referred to.
+ * Reference dereference() const;
+ * // Access the value at some other location
+ * Reference elementAt(n) const;
+ *
+ * // Compare for equality with j
+ * bool equals(j);
+ *
+ * // position the iterator at the next element.
+ * void increment()
+ *
+ * // position the iterator at the previous element.
+ * void decrement()
+ *
+ * // advance the iterator by a number of positions-
+ * void advance(DifferenceType n);
+ * // calculate the distance to another iterator.
+ * // One should incorporate an assertion wether
+ * // the same containers are referenced
+ * DifferenceType distanceTo(j) const;
+ * \endcode
+ *
+ * For an elaborate explanation see the
+ * <A HREF="http://www.sgi.com/tech/stl/iterator_traits.html">STL Documentation</A>
+ */
+ typedef T DerivedType;
+
+ /**
+ * @brief The type of value accessed through the iterator.
+ */
+ typedef V Value;
+
+ /**
+ * @brief The pointer to the Value.
+ */
+ typedef V* Pointer;
+
+ /**
+ * @brief The type of the difference between two positions.
+ */
+ typedef D DifferenceType;
+
+ /**
+ * @brief The type of the reference to the values accessed.
+ */
+ typedef R Reference;
+
+ /** @brief Dereferencing operator. */
+ Reference operator*() const
+ {
+ return static_cast<DerivedType const*>(this)->dereference();
+ }
+
+ Pointer operator->() const
+ {
+ return &(static_cast<const DerivedType *>(this)->dereference());
+ }
+
+ /**
+ * @brief Get the element n positions from the current one.
+ * @param n The distance to the element.
+ * @return The element at that distance.
+ */
+ Reference operator[](DifferenceType n) const
+ {
+ return static_cast<const DerivedType *>(this)->elementAt(n);
+ }
+
+ /** @brief Preincrement operator. */
+ DerivedType& operator++()
+ {
+ static_cast<DerivedType *>(this)->increment();
+ return *static_cast<DerivedType *>(this);
+ }
+
+ /** @brief Postincrement operator. */
+ DerivedType operator++(int)
+ {
+ DerivedType tmp(static_cast<DerivedType const&>(*this));
+ this->operator++();
+ return tmp;
+ }
+
+ DerivedType& operator+=(DifferenceType n)
+ {
+ static_cast<DerivedType *>(this)->advance(n);
+ return *static_cast<DerivedType *>(this);
+ }
+
+ DerivedType operator+(DifferenceType n) const
+ {
+ DerivedType tmp(static_cast<DerivedType const&>(*this));
+ tmp.advance(n);
+ return tmp;
+ }
+
+
+ /** @brief Predecrement operator. */
+ DerivedType& operator--()
+ {
+ static_cast<DerivedType *>(this)->decrement();
+ return *static_cast<DerivedType *>(this);
+ }
+
+ /** @brief Postdecrement operator. */
+ DerivedType operator--(int)
+ {
+ DerivedType tmp(static_cast<DerivedType const&>(*this));
+ this->operator--();
+ return tmp;
+ }
+
+ DerivedType& operator-=(DifferenceType n)
+ {
+ static_cast<DerivedType *>(this)->advance(-n);
+ return *static_cast<DerivedType *>(this);
+ }
+
+ DerivedType operator-(DifferenceType n) const
+ {
+ DerivedType tmp(static_cast<DerivedType const&>(*this));
+ tmp.advance(-n);
+ return tmp;
+ }
+
+
+ };
+
+ /**
+ * @brief Checks for equality.
+ *
+ * This operation is only defined if either D2
+ * is convertible to D1 or vice versa. If that is
+ * not the case the compiler will report an error
+ * as EnableIfInterOperable<D1,D2,bool>::type is
+ * not defined.
+ *
+ */
+ template<class T1, class V1, class R1, class D,
+ class T2, class V2, class R2>
+ inline typename EnableIfInterOperable<T1,T2,bool>::type
+ operator==(const RandomAccessIteratorFacade<T1,V1,R1,D>& lhs,
+ const RandomAccessIteratorFacade<T2,V2,R2,D>& rhs)
+ {
+ if(Conversion<T2,T1>::exists)
+ return static_cast<const T1&>(lhs).equals(static_cast<const T2&>(rhs));
+ else
+ return static_cast<const T2&>(rhs).equals(static_cast<const T1&>(lhs));
+ }
+
+ /**
+ * @brief Checks for inequality.
+ *
+ * This operation is only defined if either D2
+ * is convertible to D1 or vice versa. If that is
+ * not the case the compiler will report an error
+ * as EnableIfInterOperable<D1,D2,bool>::type is
+ * not defined.
+ *
+ */
+ template<class T1, class V1, class R1, class D,
+ class T2, class V2, class R2>
+ inline typename EnableIfInterOperable<T1,T2,bool>::type
+ operator!=(const RandomAccessIteratorFacade<T1,V1,R1,D>& lhs,
+ const RandomAccessIteratorFacade<T2,V2,R2,D>& rhs)
+ {
+ if(Conversion<T2,T1>::exists)
+ return !static_cast<const T1&>(lhs).equals(static_cast<const T2&>(rhs));
+ else
+ return !static_cast<const T2&>(rhs).equals(static_cast<const T1&>(lhs));
+ }
+
+ /**
+ * @brief Comparison operator.
+ *
+ * This operation is only defined if either D2
+ * is convertible to D1 or vice versa. If that is
+ * not the case the compiler will report an error
+ * as EnableIfInterOperable<D1,D2,bool>::type is
+ * not defined.
+ *
+ */
+ template<class T1, class V1, class R1, class D,
+ class T2, class V2, class R2>
+ inline typename EnableIfInterOperable<T1,T2,bool>::type
+ operator<(const RandomAccessIteratorFacade<T1,V1,R1,D>& lhs,
+ const RandomAccessIteratorFacade<T2,V2,R2,D>& rhs)
+ {
+ if(Conversion<T2,T1>::exists)
+ return static_cast<const T1&>(lhs).distanceTo(static_cast<const T2&>(rhs))>0;
+ else
+ return static_cast<const T2&>(rhs).distanceTo(static_cast<const T1&>(lhs))<0;
+ }
+
+
+ /**
+ * @brief Comparison operator.
+ *
+ * This operation is only defined if either D2
+ * is convertible to D1 or vice versa. If that is
+ * not the case the compiler will report an error
+ * as EnableIfInterOperable<D1,D2,bool>::type is
+ * not defined.
+ *
+ */
+ template<class T1, class V1, class R1, class D,
+ class T2, class V2, class R2>
+ inline typename EnableIfInterOperable<T1,T2,bool>::type
+ operator<=(const RandomAccessIteratorFacade<T1,V1,R1,D>& lhs,
+ const RandomAccessIteratorFacade<T2,V2,R2,D>& rhs)
+ {
+ if(Conversion<T2,T1>::exists)
+ return static_cast<const T1&>(lhs).distanceTo(static_cast<const T2&>(rhs))>=0;
+ else
+ return static_cast<const T2&>(rhs).distanceTo(static_cast<const T1&>(lhs))<=0;
+ }
+
+
+ /**
+ * @brief Comparison operator.
+ *
+ * This operation is only defined if either D2
+ * is convertible to D1 or vice versa. If that is
+ * not the case the compiler will report an error
+ * as EnableIfInterOperable<D1,D2,bool>::type is
+ * not defined.
+ *
+ */
+ template<class T1, class V1, class R1, class D,
+ class T2, class V2, class R2>
+ inline typename EnableIfInterOperable<T1,T2,bool>::type
+ operator>(const RandomAccessIteratorFacade<T1,V1,R1,D>& lhs,
+ const RandomAccessIteratorFacade<T2,V2,R2,D>& rhs)
+ {
+ if(Conversion<T2,T1>::exists)
+ return static_cast<const T1&>(lhs).distanceTo(static_cast<const T2&>(rhs))<0;
+ else
+ return static_cast<const T2&>(rhs).distanceTo(static_cast<const T1&>(lhs))>0;
+ }
+
+ /**
+ * @brief Comparison operator.
+ *
+ * This operation is only defined if either D2
+ * is convertible to D1 or vice versa. If that is
+ * not the case the compiler will report an error
+ * as EnableIfInterOperable<D1,D2,bool>::type is
+ * not defined.
+ *
+ */
+ template<class T1, class V1, class R1, class D,
+ class T2, class V2, class R2>
+ inline typename EnableIfInterOperable<T1,T2,bool>::type
+ operator>=(const RandomAccessIteratorFacade<T1,V1,R1,D>& lhs,
+ const RandomAccessIteratorFacade<T2,V2,R2,D>& rhs)
+ {
+ if(Conversion<T2,T1>::exists)
+ return static_cast<const T1&>(lhs).distanceTo(static_cast<const T2&>(rhs))<=0;
+ else
+ return static_cast<const T2&>(rhs).distanceTo(static_cast<const T1&>(lhs))>=0;
+ }
+
+ /**
+ * @brief Calculates the difference between two pointers.
+ *
+ * This operation is only defined if either D2
+ * is convertible to D1 or vice versa. If that is
+ * not the case the compiler will report an error
+ * as EnableIfInterOperable<D1,D2,bool>::type is
+ * not defined.
+ *
+ */
+ template<class T1, class V1, class R1, class D,
+ class T2, class V2, class R2>
+ inline typename EnableIfInterOperable<T1,T2,D>::type
+ operator-(const RandomAccessIteratorFacade<T1,V1,R1,D>& lhs,
+ const RandomAccessIteratorFacade<T2,V2,R2,D>& rhs)
+ {
+ if(Conversion<T2,T1>::exists)
+ return -static_cast<const T1&>(lhs).distanceTo(static_cast<const T2&>(rhs));
+ else
+ return static_cast<const T2&>(rhs).distanceTo(static_cast<const T1&>(lhs));
+ }
+
+ /** @} */
+}
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_LCM_HH
+#define DUNE_LCM_HH
+
+/** \file
+ * \brief Statically compute the least common multiple of two integers
+ */
+
+#include <dune/common/static_assert.hh>
+#include <dune/common/gcd.hh>
+
+namespace Dune
+{
+
+ /**
+ * @addtogroup Common
+ * @{
+ */
+ /**
+ * @file
+ * This file provides template constructs for calculation the
+ * least common multiple.
+ */
+
+ /**
+ * @brief Calculate the least common multiple of two numbers
+ */
+ template<long m, long n>
+ struct Lcm
+ {
+ static void conceptCheck()
+ {
+ dune_static_assert(0<m, "m must be positive!");
+ dune_static_assert(0<n, "n must be positive!");
+ }
+ /**
+ * @brief The least common multiple of the template parameters
+ * m and n.
+ */
+ const static long value = (m/Gcd<m,n>::value)*n;
+ };
+}
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_COMMON_LRU_HH
+#define DUNE_COMMON_LRU_HH
+
+#include <list>
+#include <utility>
+#include <map>
+
+#include <dune/common/exceptions.hh>
+
+/** @file
+ @author Christian Engwer
+ @brief LRU Cache Container, using an STL like interface
+ */
+
+namespace Dune {
+
+ namespace {
+
+ /*
+ hide the default traits in an empty namespace
+ */
+ template <typename _Key, typename _Tp,
+ typename _Alloc = std::allocator<_Tp> >
+ struct _lru_default_traits
+ {
+ typedef _Key key_type;
+ typedef _Alloc allocator;
+ typedef std::list< std::pair<_Key, _Tp> > list_type;
+ typedef typename list_type::iterator iterator;
+ typedef typename std::less<key_type> cmp;
+ typedef std::map< key_type, iterator, cmp,
+ typename allocator::template rebind<std::pair<const key_type, iterator> >::other > map_type;
+ };
+
+ } // end empty namespace
+
+ /**
+ @brief LRU Cache Container
+
+ Implementation of an LRU (least recently used) cache
+ container. This implementation follows the approach presented in
+ http://aim.adc.rmit.edu.au/phd/sgreuter/papers/graphite2003.pdf
+ */
+ template <typename _Key, typename _Tp,
+ typename _Traits = _lru_default_traits<_Key, _Tp> >
+ class lru
+ {
+ typedef typename _Traits::list_type list_type;
+ typedef typename _Traits::map_type map_type;
+ typedef typename _Traits::allocator allocator;
+ typedef typename map_type::iterator map_iterator;
+ typedef typename map_type::const_iterator const_map_iterator;
+
+ public:
+ typedef typename _Traits::key_type key_type;
+ typedef typename allocator::value_type value_type;
+ typedef typename allocator::pointer pointer;
+ typedef typename allocator::const_pointer const_pointer;
+ typedef typename allocator::const_reference const_reference;
+ typedef typename allocator::reference reference;
+ typedef typename allocator::size_type size_type;
+ typedef typename list_type::iterator iterator;
+ typedef typename list_type::const_iterator const_iterator;
+
+ /**
+ * Returns a read/write reference to the data of the most
+ * recently used entry.
+ */
+ reference front()
+ {
+ return _data.front().second;
+ }
+
+ /**
+ * Returns a read-only (constant) reference to the data of the
+ * most recently used entry.
+ */
+ const_reference front() const
+ {
+ return _data.front().second;
+ }
+
+ /**
+ * Returns a read/write reference to the data of the least
+ * recently used entry.
+ */
+ reference back()
+ {
+ return _data.back().second;
+ }
+
+ /**
+ * Returns a read-only (constant) reference to the data of the
+ * least recently used entry.
+ */
+ const_reference back (int i) const
+ {
+ return _data.back().second;
+ }
+
+
+ /**
+ * @brief Removes the first element.
+ */
+ const void pop_front()
+ {
+ key_type k = _data.front().first;
+ _data.pop_front();
+ _index.erase(k);
+ }
+ /**
+ * @brief Removes the last element.
+ */
+ const void pop_back()
+ {
+ key_type k = _data.back().first;
+ _data.pop_back();
+ _index.erase(k);
+ }
+
+ /**
+ * @brief Finds the element whose key is k.
+ *
+ * @return iterator
+ */
+ iterator find (const key_type & key)
+ {
+ const map_iterator it = _index.find(key);
+ if (it == _index.end()) return _data.end();
+ return it->second;
+ }
+
+ /**
+ * @brief Finds the element whose key is k.
+ *
+ * @return const_iterator
+ */
+ const_iterator find (const key_type & key) const
+ {
+ const map_iterator it = _index.find(key);
+ if (it == _index.end()) return _data.end();
+ return it->second;
+ }
+
+ /**
+ * @brief Insert a value into the container
+ *
+ * Stores value under key and marks it as most recent. If this key
+ * is already present, the associated data is replaced.
+ *
+ * @param key associated with data
+ * @param data to store
+ *
+ * @return reference of stored data
+ */
+ reference insert (const key_type & key, const_reference data)
+ {
+ std::pair<key_type, value_type> x(key, data);
+ /* insert item as mru */
+ iterator it = _data.insert(_data.begin(), x);
+ /* store index */
+ _index.insert(std::make_pair(key,it));
+
+ return it->second;
+ }
+
+ /**
+ * @copydoc touch
+ */
+ reference insert (const key_type & key)
+ {
+ return touch (key);
+ }
+
+ /**
+ * @brief mark data associated with key as most recent
+ *
+ * @return reference of stored data
+ */
+ reference touch (const key_type & key)
+ {
+ /* query _index for iterator */
+ map_iterator it = _index.find(key);
+ if (it == _index.end())
+ DUNE_THROW(Dune::RangeError,
+ "Failed to touch key " << key << ", it is not in the lru container");
+ /* update _data
+ move it to the front
+ */
+ _data.splice(_data.begin(), _data, it->second);
+ return it->second->second;
+ }
+
+ /**
+ * @brief Retrieve number of entries in the container
+ */
+ size_type size() const
+ {
+ return _data.size();
+ }
+
+ /**
+ * @brief ensure a maximum size of the container
+ *
+ * If new_size is smaller than size the oldest elements are
+ * dropped. Otherwise nothing happens.
+ */
+ void resize(size_type new_size)
+ {
+ assert(new_size <= size());
+
+ while (new_size < size())
+ pop_back();
+ }
+
+ /**
+ *
+ */
+ void clear()
+ {
+ _data.clear();
+ _index.clear();
+ }
+
+ private:
+ list_type _data;
+ map_type _index;
+
+ };
+
+} // namespace Dune
+
+#endif // DUNE_COMMON_LRU_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_MALLOC_ALLOCATOR_HH
+#define DUNE_MALLOC_ALLOCATOR_HH
+
+#include <exception>
+#include <cstdlib>
+#include <new>
+#include <utility>
+#include <dune/common/unused.hh>
+
+/**
+ * @file
+ * @brief Allocators that use malloc/free.
+ */
+namespace Dune
+{
+ /**
+ @ingroup Allocators
+ @brief Allocators implementation which simply calls malloc/free
+ */
+ template <class T>
+ class MallocAllocator {
+ public:
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T value_type;
+ template <class U> struct rebind {
+ typedef MallocAllocator<U> other;
+ };
+
+ //! create a new MallocAllocator
+ MallocAllocator() throw() {}
+ //! copy construct from an other MallocAllocator, possibly for a different result type
+ template <class U>
+ MallocAllocator(const MallocAllocator<U>&) throw() {}
+ //! cleanup this allocator
+ ~MallocAllocator() throw() {}
+
+ pointer address(reference x) const
+ {
+ return &x;
+ }
+ const_pointer address(const_reference x) const
+ {
+ return &x;
+ }
+
+ //! allocate n objects of type T
+ pointer allocate(size_type n,
+ const void* hint = 0)
+ {
+ DUNE_UNUSED_PARAMETER(hint);
+ if (n > this->max_size())
+ throw std::bad_alloc();
+
+ pointer ret = static_cast<pointer>(std::malloc(n * sizeof(T)));
+ if (!ret)
+ throw std::bad_alloc();
+ return ret;
+ }
+
+ //! deallocate n objects of type T at address p
+ void deallocate(pointer p, size_type n)
+ {
+ DUNE_UNUSED_PARAMETER(n);
+ std::free(p);
+ }
+
+ //! max size for allocate
+ size_type max_size() const throw()
+ {
+ return size_type(-1) / sizeof(T);
+ }
+
+ //! copy-construct an object of type T (i.e. make a placement new on p)
+ void construct(pointer p, const T& val)
+ {
+ ::new((void*)p)T(val);
+ }
+#if ( HAVE_VARIADIC_TEMPLATES && HAVE_RVALUE_REFERENCES ) || DOXYGEN
+ //! construct an object of type T from variadic parameters
+ //! \note works only with newer C++ compilers
+ template<typename ... _Args>
+ void construct(pointer p, _Args&&... __args)
+ {
+ ::new((void *)p)T(std::forward<_Args>(__args) ...);
+ }
+#endif
+ //! destroy an object of type T (i.e. call the destructor)
+ void destroy(pointer p)
+ {
+ p->~T();
+ }
+ };
+}
+
+#endif // DUNE_MALLOC_ALLOCATOR_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_MATH_HH
+#define DUNE_MATH_HH
+
+/** \file
+ * \brief Some useful basic math stuff
+ */
+
+#include <cmath>
+#include <complex>
+
+namespace Dune
+{
+
+ /**
+ \brief Provides commonly used mathematical constants.
+
+ a struct that is specialized for types repesenting real or complex
+ numbers. I provides commonly used mathematical constants with the
+ required accuary for the specified type.
+ */
+ template< class Field >
+ struct MathematicalConstants;
+
+ /**
+ \brief Standard implementation of MathematicalConstants.
+
+ This implementation will work with all built-in floating point
+ types. It provides
+
+ * e as std::exp(1.0)
+ * pi as std::acos(-1.0)
+
+ */
+ template< class T >
+ struct StandardMathematicalConstants
+ {
+ static T e ()
+ {
+ static const T e = std::exp( T( 1 ) );
+ return e;
+ }
+
+ static T pi ()
+ {
+ static const T pi = std::acos( T( -1 ) );
+ return pi;
+ }
+ };
+
+
+#ifndef DOXYGEN
+ // MathematicalConstants for float
+ // -------------------------------
+
+ template<>
+ struct MathematicalConstants< float >
+ : public StandardMathematicalConstants< float >
+ {};
+
+
+
+ // MathematicalConstants for double
+ // --------------------------------
+
+ template<>
+ struct MathematicalConstants< double >
+ : public StandardMathematicalConstants< double >
+ {};
+
+
+
+ // MathematicalConstants for long double
+ // -------------------------------------
+
+ template<>
+ struct MathematicalConstants< long double >
+ : public StandardMathematicalConstants< long double >
+ {};
+#endif // DOXYGEN
+
+
+ //! Calculates the factorial of m at compile time
+ template <int m>
+ struct Factorial
+ {
+ //! factorial stores m!
+ enum { factorial = m * Factorial<m-1>::factorial };
+ };
+
+ //! end of recursion of factorial via specialization
+ template <>
+ struct Factorial<0>
+ {
+ // 0! = 1
+ enum { factorial = 1 };
+ };
+
+ //! compute conjugate complex of x
+ // conjugate complex does nothing for non-complex types
+ template<class K>
+ inline K conjugateComplex (const K& x)
+ {
+ return x;
+ }
+
+#ifndef DOXYGEN
+ // specialization for complex
+ template<class K>
+ inline std::complex<K> conjugateComplex (const std::complex<K>& c)
+ {
+ return std::complex<K>(c.real(),-c.imag());
+ }
+#endif
+
+ //! Return the sign of the value
+ template <class T>
+ int sign(const T& val)
+ {
+ return (val < 0 ? -1 : 1);
+ }
+
+}
+
+#endif // #ifndef DUNE_MATH_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id: fvector.hh 5262 2008-09-07 09:03:38Z christi $
+#ifndef DUNE_MATVECTRAITS_HH
+#define DUNE_MATVECTRAITS_HH
+
+/** \file
+ * \brief Documentation of the traits classes you need to write for each implementation of DenseVector or DenseMatrix
+ */
+
+namespace Dune {
+
+ /**
+ @addtogroup DenseMatVec
+ \brief Type Traits to retrieve types associated with an implementation of Dune::DenseVector or Dune::DenseMatrix
+
+ you have to specialize this class for every implementation of DenseVector or DenseMatrix.
+
+ \code
+ //! export the type of the derived class (e.g. FieldVector<K,SIZE>)
+ typedef ... derived_type;
+ //! export the type of the stored values
+ typedef ... value_type;
+ //! export the type representing the size information
+ typedef ... size_type;
+ \endcode
+
+ */
+ template<class T>
+ struct DenseMatVecTraits {};
+
+} // end namespace Dune
+
+#endif // DUNE_FTRAITS_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef MISC_HH
+#define MISC_HH
+
+#warning This file is deprecated. Its contents have moved to stringutility.hh and math.hh, \
+ or will disappear completely.
+
+/** \file
+ \brief Miscellaneous helper stuff
+ */
+
+#include <algorithm>
+#include <cstddef>
+#include <cstring>
+#include <cstdio>
+#include <iostream>
+#include <iomanip>
+#include <iterator>
+#include <sstream>
+#include <complex>
+
+#include <dune/common/deprecated.hh>
+#include "exceptions.hh"
+#include <dune/common/typetraits.hh>
+#include <dune/common/stringutility.hh>
+#include <dune/common/math.hh>
+
+namespace Dune {
+
+
+ /** @addtogroup Common
+
+ @{
+ */
+
+ /** \brief Compute the square of T */
+ /**
+ * \code
+ *#include <dune/common/misc.hh>
+ * \endcode
+ */
+ template<class T>
+ T SQR (T t) DUNE_DEPRECATED_MSG("Use method sqr from math.hh instead");
+
+ template<class T>
+ T SQR (T t)
+ {
+ return t*t;
+ }
+
+ //! Calculates m^p at compile time
+ template <int m, int p>
+ struct DUNE_DEPRECATED_MSG ("Use class StaticPower from file power.hh instead")Power_m_p
+ {
+ // power stores m^p
+ enum { power = (m * Power_m_p<m,p-1>::power ) };
+ };
+
+ //! end of recursion via specialization
+ template <int m>
+ struct DUNE_DEPRECATED_MSG ("Use class StaticPower from file power.hh instead")Power_m_p< m , 0>
+ {
+ // m^0 = 1
+ enum { power = 1 };
+ };
+
+ //********************************************************************
+ //
+ // generate filenames with timestep number in it
+ //
+ //********************************************************************
+
+ /** \brief Generate filenames with timestep number in it */
+ inline std::string genFilename(const std::string& path,
+ const std::string& fn,
+ int ntime,
+ int precision = 6)
+ {
+ std::ostringstream name;
+
+ if(path.size() > 0)
+ {
+ name << path;
+ name << "/";
+ }
+ name << fn << std::setw(precision) << std::setfill('0') << ntime;
+
+ // Return the string corresponding to the stringstream
+ return name.str();
+ }
+
+
+ /** @} */
+
+}
+
+
+#endif
--- /dev/null
+/* This file determines the order how things appear in the doxygen
+ documentation within the dune-common module. It works like this:
+
+ @defgroup commands appear only in this file here which is
+ parsed before the other files (because it is mentioned first
+ in the Doxyfile).
+
+ Only @addtogroup is used in the code documentation.
+*/
+
+ /**
+ @defgroup COGeometryType GeometryType
+ @ingroup Common
+ */
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_MPICOLLECTIVECOMMUNICATION_HH
+#warning dune/common/mpicollectivecommunication.hh is deprecated, please use dune/common/parallel/mpicollectivecommunication.hh
+#include "parallel/mpicollectivecommunication.hh"
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_COMMON_MPIGUARD_HH
+#warning dune/common/mpiguard.hh is deprecated, please use dune/common/parallel/mpiguard.hh
+#include "parallel/mpiguard.hh"
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_MPIHELPER
+#warning dune/common/mpihelper.hh is deprecated, please use dune/common/parallel/mpihelper.hh
+#include "parallel/mpihelper.hh"
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_MPITRAITS_HH
+#warning dune/common/mpitraits.hh is deprecated, please use dune/common/parallel/mpitraits.hh
+#include "parallel/mpitraits.hh"
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_NULLPTR_HH
+#define DUNE_NULLPTR_HH
+
+/** \file
+ * \brief Fallback implementation of the nullptr object in C++0x
+ */
+
+#if ! HAVE_NULLPTR
+
+/**
+ \brief Fallback implementation of nullptr
+
+ see C++ proposal
+ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf
+ */
+const // this is a const object...
+class dune_nullptr_t { // of type nullptr_t
+public:
+ template<class T> // convertible to any type
+ operator T*() const // of null non-member
+ { return 0; } // pointer...
+ template<class C, class T> // or any type of null
+ operator T C::*() const // member pointer...
+ { return 0; }
+private:
+ void operator&() const; // whose address can't be taken
+} nullptr = {}; // and whose name is nullptr
+
+namespace Dune {
+ typedef dune_nullptr_t nullptr_t;
+}
+
+template<class T>
+bool operator == (T* t, dune_nullptr_t)
+{
+ return (t == static_cast<T*>(nullptr));
+}
+
+template<class T>
+bool operator == (dune_nullptr_t, T* t)
+{
+ return (t == static_cast<T*>(nullptr));
+}
+
+#else
+
+#include <cstddef>
+
+namespace Dune {
+ using std::nullptr_t;
+}
+
+#endif // HAVE_NULLPTR
+
+#endif // DUNE_NULLPTR_HH
--- /dev/null
+Makefile.in
+Makefile
+
--- /dev/null
+add_subdirectory("test" EXCLUDE_FROM_ALL)
+
+#install headers
+install(FILES
+ collectivecommunication.hh
+ communicator.hh
+ indexset.hh
+ indicessyncer.hh
+ interface.hh
+ localindex.hh
+ mpicollectivecommunication.hh
+ mpiguard.hh
+ mpihelper.hh
+ mpitraits.hh
+ plocalindex.hh
+ remoteindices.hh
+ selection.hh
+ variablesizecommunicator.hh
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/common/parallel)
+
--- /dev/null
+# $Id$
+
+SUBDIRS = test
+
+parallelincludedir = $(includedir)/dune/common/parallel
+parallelinclude_HEADERS = \
+ collectivecommunication.hh \
+ communicator.hh \
+ indexset.hh \
+ indicessyncer.hh \
+ interface.hh \
+ localindex.hh \
+ mpicollectivecommunication.hh \
+ mpiguard.hh \
+ mpihelper.hh \
+ mpitraits.hh \
+ plocalindex.hh \
+ remoteindices.hh \
+ selection.hh \
+ variablesizecommunicator.hh
+
+include $(top_srcdir)/am/global-rules
+
+EXTRA_DIST = CMakeLists.txt
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_COLLECTIVECOMMUNICATION_HH
+#define DUNE_COLLECTIVECOMMUNICATION_HH
+/*!
+ \file
+ \brief Implements an utility class that provides
+ collective communication methods for sequential programs.
+
+ \ingroup ParallelCommunication
+ */
+#include <iostream>
+#include <complex>
+#include <algorithm>
+
+#include <dune/common/exceptions.hh>
+
+/*! \defgroup ParallelCommunication Parallel Communication
+ \ingroup Common
+
+ \brief Abstractions for paralle computing
+
+ Dune offers an abstraction to the basic methods of parallel
+ communication. It allows to switch parallel features on and off,
+ without changing the code. This is done using either CollectiveCommunication
+ or MPICollectiveCommunication.
+
+ */
+
+/*!
+ \file
+ \brief An abstraction to the basic methods of parallel communication,
+ following the message-passing paradigm.
+ \ingroup ParallelCommunication
+ */
+
+namespace Dune
+{
+
+ /* define some type that definitely differs from MPI_Comm */
+ struct No_Comm {};
+
+
+ /*! @brief Collective communication interface and sequential default implementation
+
+ CollectiveCommunication offers an abstraction to the basic methods
+ of parallel communication, following the message-passing
+ paradigm. It allows to switch parallel features on and off, without
+ changing the code. Currently only MPI and sequential code are
+ supported.
+
+ A CollectiveCommunication object is returned by all grids (also
+ the sequential ones) in order to allow code to be written in
+ a transparent way for sequential and parallel grids.
+
+ This class provides a default implementation for sequential grids.
+ The number of processes involved is 1, any sum, maximum, etc. returns
+ just its input argument and so on.
+
+ In specializations one can implement the real thing using appropriate
+ communication functions, e.g. there exists an implementation using
+ the Message Passing %Interface (MPI), see Dune::CollectiveCommunication<MPI_Comm>.
+
+ Moreover, the communication subsystem used by an implementation
+ is not visible in the interface, i.e. Dune grid implementations
+ are not restricted to MPI.
+
+ \ingroup ParallelCommunication
+ */
+ template<typename C>
+ class CollectiveCommunication
+ {
+ public:
+ //! Construct default object
+ CollectiveCommunication()
+ {}
+ CollectiveCommunication (const C&)
+ {}
+
+ //! Return rank, is between 0 and size()-1
+ int rank () const
+ {
+ return 0;
+ }
+
+ //! Number of processes in set, is greater than 0
+ int size () const
+ {
+ return 1;
+ }
+
+ /** @brief Compute the sum of the argument over all processes and
+ return the result in every process. Assumes that T has an operator+
+ */
+ template<typename T>
+ T sum (T& in) const // MPI does not know about const :-(
+ {
+ return in;
+ }
+
+ /** @brief Compute the sum over all processes for each component of an array and return the result
+ in every process. Assumes that T has an operator+
+ */
+ template<typename T>
+ int sum (T* inout, int len) const
+ {
+ return 0;
+ }
+
+ /** @brief Compute the product of the argument over all processes and
+ return the result in every process. Assumes that T has an operator*
+ */
+ template<typename T>
+ T prod (T& in) const // MPI does not know about const :-(
+ {
+ return in;
+ }
+
+ /** @brief Compute the product over all processes
+ for each component of an array and return the result
+ in every process. Assumes that T has an operator*
+ */
+ template<typename T>
+ int prod (T* inout, int len) const
+ {
+ return 0;
+ }
+
+ /** @brief Compute the minimum of the argument over all processes and
+ return the result in every process. Assumes that T has an operator<
+ */
+ template<typename T>
+ T min (T& in) const // MPI does not know about const :-(
+ {
+ return in;
+ }
+
+ /** @brief Compute the minimum over all processes
+ for each component of an array and return the result
+ in every process. Assumes that T has an operator<
+ */
+ template<typename T>
+ int min (T* inout, int len) const
+ {
+ return 0;
+ }
+
+ /** @brief Compute the maximum of the argument over all processes and
+ return the result in every process. Assumes that T has an operator<
+ */
+ template<typename T>
+ T max (T& in) const // MPI does not know about const :-(
+ {
+ return in;
+ }
+
+ /** @brief Compute the maximum over all processes
+ for each component of an array and return the result
+ in every process. Assumes that T has an operator<
+ */
+ template<typename T>
+ int max (T* inout, int len) const
+ {
+ return 0;
+ }
+
+ /** @brief Wait until all processes have arrived at this point in the program.
+ */
+ int barrier () const
+ {
+ return 0;
+ }
+
+ /** @brief Distribute an array from the process with rank root to all other processes
+ */
+ template<typename T>
+ int broadcast (T* inout, int len, int root) const
+ {
+ return 0;
+ }
+
+ /** @brief Gather arrays on root task.
+ *
+ * Each process sends its in array of length len to the root process
+ * (including the root itself). In the root process these arrays are stored in rank
+ * order in the out array which must have size len * number of processes.
+ * @param[in] in The send buffer with the data to send.
+ * @param[out] out The buffer to store the received data in. Might have length zero on non-root
+ * tasks.
+ * @param[in] len The number of elements to send on each task.
+ * @param[out] root The root task that gathers the data.
+ */
+ template<typename T>
+ int gather (T* in, T* out, int len, int root) const // note out must have same size as in
+ {
+ for (int i=0; i<len; i++)
+ out[i] = in[i];
+ return 0;
+ }
+
+ /** @brief Scatter array from a root to all other task.
+ *
+ * The root process sends the elements with index from k*len to (k+1)*len-1 in its array to
+ * task k, which stores it at index 0 to len-1.
+ * @param[in] send The array to scatter. Might have length zero on non-root
+ * tasks.
+ * @param[out] recv The buffer to store the received data in. Upon completion of the
+ * method each task will have same data stored there as the one in
+ * send buffer of the root task before.
+ * @param[in] len The number of elements in the recv buffer.
+ * @param[out] root The root task that gathers the data.
+ */
+ template<typename T>
+ int scatter (T* send, T* recv, int len, int root) const // note out must have same size as in
+ {
+ for (int i=0; i<len; i++)
+ recv[i] = send[i];
+ return 0;
+ }
+
+ /**
+ * @brief Gathers data from all tasks and distribute it to all.
+ *
+ * The block of data sent from the jth process is received by every
+ * process and placed in the jth block of the buffer recvbuf.
+ *
+ * @param[in] sbuf The buffer with the data to send. Has to be the same for
+ * each task.
+ * @param[in] count The number of elements to send by any process.
+ * @param[out] rbuf The receive buffer for the data. Has to be of size
+ * notasks*count, with notasks being the number of tasks in the communicator.
+ */
+ template<typename T>
+ int allgather(T* sbuf, int count, T* rbuf) const
+ {
+ for(T* end=sbuf+count; sbuf < end; ++sbuf, ++rbuf)
+ *rbuf=*sbuf;
+ return 0;
+ }
+
+ /**
+ * @brief Compute something over all processes
+ * for each component of an array and return the result
+ * in every process.
+ *
+ * The template parameter BinaryFunction is the type of
+ * the binary function to use for the computation
+ *
+ * @param inout The array to compute on.
+ * @param len The number of components in the array
+ */
+ template<typename BinaryFunction, typename Type>
+ int allreduce(Type* inout, int len) const
+ {
+ return 0;
+ }
+
+ /**
+ * @brief Compute something over all processes
+ * for each component of an array and return the result
+ * in every process.
+ *
+ * The template parameter BinaryFunction is the type of
+ * the binary function to use for the computation
+ *
+ * @param in The array to compute on.
+ * @param out The array to store the results in.
+ * @param len The number of components in the array
+ */
+ template<typename BinaryFunction, typename Type>
+ void allreduce(Type* in, Type* out, int len) const
+ {
+ std::copy(in, in+len, out);
+ return;
+ }
+
+ };
+}
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+#ifndef DUNE_COMMUNICATOR
+#define DUNE_COMMUNICATOR
+
+#include "remoteindices.hh"
+#include "interface.hh"
+#include <dune/common/exceptions.hh>
+#include <dune/common/typetraits.hh>
+#include <dune/common/stdstreams.hh>
+
+#if HAVE_MPI
+// MPI header
+#include <mpi.h>
+
+namespace Dune
+{
+ /** @defgroup Common_Parallel Parallel Computing based on Indexsets
+ * @ingroup ParallelCommunication
+ * @brief Provides classes for syncing distributed indexed
+ * data structures.
+ *
+ * In a parallel representation a container \f$x\f$,
+ * e.g. a plain C-array, cannot be stored with all entries on each process
+ * because of limited memory and efficiency reasons. Therefore
+ * it is represented by individual
+ * pieces \f$x_p\f$, \f$p=0, \ldots, P-1\f$, where \f$x_p\f$ is the piece stored on
+ * process \f$p\f$ of the \f$P\f$ processes participating in the calculation.
+ * Although the global representation of the container is not
+ * available on any process, a process \f$p\f$ needs to know how the entries
+ * of it's local piece \f$x_p\f$ correspond to the entries of the global
+ * container \f$x\f$, which would be used in a sequential program. In this
+ * module we present classes describing the mapping of the local pieces
+ * to the global
+ * view and the communication interfaces.
+ *
+ * @section IndexSet Parallel Index Sets
+ *
+ * Form an abstract point of view a random access container \f$x: I
+ * \rightarrow K\f$ provides a
+ * mapping from an index set \f$I \subset N_0\f$ onto a set of objects
+ * \f$K\f$. Note that we do not require \f$I\f$ to be consecutive. The piece
+ * \f$x_p\f$ of the container \f$x\f$ stored on process \f$p\f$ is a mapping \f$x_p:I_p
+ * \rightarrow K\f$, where \f$I_p \subset I\f$. Due to efficiency the entries
+ * of \f$x_p\f$ should be stored in consecutive memory.
+ *
+ * This means that for the local computation the data must be addressable
+ * by a consecutive index starting from \f$0\f$. When using adaptive
+ * discretisation methods there might be the need to reorder the indices
+ * after adding and/or deleting some of the discretisation
+ * points. Therefore this index does not have to be persistent. Further
+ * on we will call this index <em>local index</em>.
+ *
+ * For the communication phases of our algorithms these locally stored
+ * entries must also be addressable by a global identifier to be able to
+ * store the received values tagged with the global identifiers at the
+ * correct local index in the consecutive local memory chunk. To ease the
+ * addition and removal of discretisation points this global identifier has
+ * to be persistent. Further on we will call this global identifier
+ * <em>global index</em>.
+ *
+ * Classes to build the mapping are ParallelIndexSet and ParallelLocalIndex.
+ * As these just provide a mapping from the global index to the local index,
+ * the wrapper class GlobalLookupIndexSet facilitates the reverse lookup.
+ *
+ * @section remote Remote Index Information
+ *
+ * To setup communication between the processes every process needs to
+ * know what indices are also known to other processes and what
+ * attributes are attached to them on the remote side. This information is
+ * calculated and encapsulated in class RemoteIndices.
+ *
+ * @section comm Communication
+ *
+ * Based on the information about the distributed index sets, data
+ * independent interfaces between different sets of the index sets
+ * can be setup using the class Interface. For the actual communication
+ * data dependant communicators can be setup using BufferedCommunicator,
+ * DatatypeCommunicator VariableSizeCommunicator based on the interface
+ * information. In contrast to the former
+ * the latter is independant of the class Interface can work on a map
+ * from process number to a pair of index lists describing which local indices
+ * are send and received from that processs, respectively.
+ */
+ /** @addtogroup Common_Parallel
+ *
+ * @{
+ */
+ /**
+ * @file
+ * @brief Provides utility classes for syncing distributed data via
+ * MPI communication.
+ * @author Markus Blatt
+ */
+
+ /**
+ * @brief Flag for marking indexed data structures where data at
+ * each index is of the same size.
+ * @see VariableSize
+ */
+ struct SizeOne
+ {};
+
+ /**
+ * @brief Flag for marking indexed data structures where the data at each index may
+ * be a variable multiple of another type.
+ * @see SizeOne
+ */
+ struct VariableSize
+ {};
+
+
+ /**
+ * @brief Default policy used for communicating an indexed type.
+ *
+ * This
+ */
+ template<class V>
+ struct CommPolicy
+ {
+ /**
+ * @brief The type the policy is for.
+ *
+ * It has to provide the mode
+ * \code Type::IndexedType operator[](int i);\endcode
+ * for
+ * the access of the value at index i and a typedef IndexedType.
+ * It is assumed
+ * that only one entry is at each index (as in scalar
+ * vector.
+ */
+ typedef V Type;
+
+ /**
+ * @brief The type we get at each index with operator[].
+ *
+ * The default is the value_type typedef of the container.
+ */
+ typedef typename V::value_type IndexedType;
+
+ /**
+ * @brief Whether the indexed type has variable size or there
+ * is always one value at each index.
+ */
+ typedef SizeOne IndexedTypeFlag;
+
+ /**
+ * @brief Get the address of entry at an index.
+ *
+ * The default implementation uses operator[] to
+ * get the address.
+ * @param v An existing representation of the type that has more elements than index.
+ * @param index The index of the entry.
+ */
+ static const void* getAddress(const V& v, int index);
+
+ /**
+ * @brief Get the number of primitve elements at that index.
+ *
+ * The default always returns 1.
+ */
+ static int getSize(const V&, int index);
+ };
+
+ template<class K, int n> class FieldVector;
+
+ template<class B, class A> class VariableBlockVector;
+
+ template<class K, class A, int n>
+ struct CommPolicy<VariableBlockVector<FieldVector<K, n>, A> >
+ {
+ typedef VariableBlockVector<FieldVector<K, n>, A> Type;
+
+ typedef typename Type::B IndexedType;
+
+ typedef VariableSize IndexedTypeFlag;
+
+ static const void* getAddress(const Type& v, int i);
+
+ static int getSize(const Type& v, int i);
+ };
+
+ /**
+ * @brief Error thrown if there was a problem with the communication.
+ */
+ class CommunicationError : public IOError
+ {};
+
+ /**
+ * @brief GatherScatter default implementation that just copies data.
+ */
+ template<class T>
+ struct CopyGatherScatter
+ {
+ typedef typename CommPolicy<T>::IndexedType IndexedType;
+
+ static const IndexedType& gather(const T& vec, std::size_t i);
+
+ static void scatter(T& vec, const IndexedType& v, std::size_t i);
+
+ };
+
+ /**
+ * @brief An utility class for communicating distributed data structures via MPI datatypes.
+ *
+ * This communicator creates special MPI datatypes that address the non contiguous elements
+ * to be send and received. The idea was to prevent the copying to an additional buffer and
+ * the mpi implementation decide whether to allocate buffers or use buffers offered by the
+ * interconnection network.
+ *
+ * Unfortunately the implementation of MPI datatypes seems to be poor. Therefore for most MPI
+ * implementations using a BufferedCommunicator will be more efficient.
+ */
+ template<typename T>
+ class DatatypeCommunicator : public InterfaceBuilder
+ {
+ public:
+
+ /**
+ * @brief Type of the index set.
+ */
+ typedef T ParallelIndexSet;
+
+ /**
+ * @brief Type of the underlying remote indices class.
+ */
+ typedef Dune::RemoteIndices<ParallelIndexSet> RemoteIndices;
+
+ /**
+ * @brief The type of the global index.
+ */
+ typedef typename RemoteIndices::GlobalIndex GlobalIndex;
+
+ /**
+ * @brief The type of the attribute.
+ */
+ typedef typename RemoteIndices::Attribute Attribute;
+
+ /**
+ * @brief The type of the local index.
+ */
+ typedef typename RemoteIndices::LocalIndex LocalIndex;
+
+ /**
+ * @brief Creates a new DatatypeCommunicator.
+ */
+ DatatypeCommunicator();
+
+ /**
+ * @brief Destructor.
+ */
+ ~DatatypeCommunicator();
+
+ /**
+ * @brief Builds the interface between the index sets.
+ *
+ * Has to be called before the actual communication by forward or backward
+ * can be called. Nonpublic indices will be ignored!
+ *
+ *
+ * The types T1 and T2 are classes representing a set of
+ * enumeration values of type DatatypeCommunicator::Attribute.
+ * They have to provide
+ * a (static) method
+ * \code
+ * bool contains(Attribute flag) const;
+ * \endcode
+ * for checking whether the set contains a specfic flag.
+ * This functionality is for example provided the classes
+ * EnumItem, EnumRange and Combine.
+ *
+ * @param remoteIndices The indices present on remote processes.
+ * @param sourceFlags The set of attributes which mark indices we send to other
+ * processes.
+ * @param sendData The indexed data structure whose data will be send.
+ * @param destFlags The set of attributes which mark the indices we might
+ * receive values from.
+ * @param receiveData The indexed data structure for which we receive data.
+ */
+ template<class T1, class T2, class V>
+ void build(const RemoteIndices& remoteIndices, const T1& sourceFlags, V& sendData, const T2& destFlags, V& receiveData);
+
+ /**
+ * @brief Sends the primitive values from the source to the destination.
+ */
+ void forward();
+
+ /**
+ * @brief Sends the primitive values from the destination to the source.
+ */
+ void backward();
+
+ /**
+ * @brief Deallocates the MPI requests and data types.
+ */
+ void free();
+ private:
+ enum {
+ /**
+ * @brief Tag for the MPI communication.
+ */
+ commTag_ = 234
+ };
+
+ /**
+ * @brief The indices also known at other processes.
+ */
+ const RemoteIndices* remoteIndices_;
+
+ typedef std::map<int,std::pair<MPI_Datatype,MPI_Datatype> >
+ MessageTypeMap;
+
+ /**
+ * @brief The datatypes built according to the communication interface.
+ */
+ MessageTypeMap messageTypes;
+
+ /**
+ * @brief The pointer to the data whose entries we communicate.
+ */
+ void* data_;
+
+ MPI_Request* requests_[2];
+
+ /**
+ * @brief True if the request and data types were created.
+ */
+ bool created_;
+
+ /**
+ * @brief Creates the MPI_Requests for the forward communication.
+ */
+ template<class V, bool FORWARD>
+ void createRequests(V& sendData, V& receiveData);
+
+ /**
+ * @brief Creates the data types needed for the unbuffered receive.
+ */
+ template<class T1, class T2, class V, bool send>
+ void createDataTypes(const T1& source, const T2& destination, V& data);
+
+ /**
+ * @brief Initiates the sending and receive.
+ */
+ void sendRecv(MPI_Request* req);
+
+ /**
+ * @brief Information used for setting up the MPI Datatypes.
+ */
+ struct IndexedTypeInformation
+ {
+ /**
+ * @brief Allocate space for setting up the MPI datatype.
+ *
+ * @param i The number of values the datatype will have.
+ */
+ void build(int i)
+ {
+ length = new int[i];
+ displ = new MPI_Aint[i];
+ size = i;
+ }
+
+ /**
+ * @brief Free the allocated space.
+ */
+ void free()
+ {
+ delete[] length;
+ delete[] displ;
+ }
+ /** @brief The number of values at each index. */
+ int* length;
+ /** @brief The displacement at each index. */
+ MPI_Aint* displ;
+ /**
+ * @brief The number of elements we send.
+ * In case of variable sizes this will differ from
+ * size.
+ */
+ int elements;
+ /**
+ * @param The number of indices in the data type.
+ */
+ int size;
+ };
+
+ /**
+ * @brief Functor for the InterfaceBuilder.
+ *
+ * It will record the information needed to build the MPI_Datatypes.
+ */
+ template<class V>
+ struct MPIDatatypeInformation
+ {
+ /**
+ * @brief Constructor.
+ * @param data The data we construct an MPI data type for.
+ */
+ MPIDatatypeInformation(const V& data) : data_(data)
+ {}
+
+ /**
+ * @brief Reserver space for the information about the datatype.
+ * @param proc The rank of the process this information is for.
+ * @param size The number of indices the datatype will contain.
+ */
+ void reserve(int proc, int size)
+ {
+ information_[proc].build(size);
+ }
+ /**
+ * @brief Add a new index to the datatype.
+ * @param proc The rank of the process this index is send to
+ * or received from.
+ * @param local The index to add.
+ */
+ void add(int proc, int local)
+ {
+ IndexedTypeInformation& info=information_[proc];
+ assert(info.elements<info.size);
+ MPI_Address( const_cast<void*>(CommPolicy<V>::getAddress(data_, local)),
+ info.displ+info.elements);
+ info.length[info.elements]=CommPolicy<V>::getSize(data_, local);
+ info.elements++;
+ }
+
+ /**
+ * @brief The information about the datatypes to send to or
+ * receive from each process.
+ */
+ std::map<int,IndexedTypeInformation> information_;
+ /**
+ * @brief A representative of the indexed data we send.
+ */
+ const V& data_;
+
+ };
+
+ };
+
+ /**
+ * @brief A communicator that uses buffers to gather and scatter
+ * the data to be send or received.
+ *
+ * Before the data is sent it it copied to a consecutive buffer and
+ * then that buffer is sent.
+ * The data is received in another buffer and then copied to the actual
+ * position.
+ */
+ class BufferedCommunicator
+ {
+
+ public:
+ /**
+ * @brief Constructor.
+ */
+ BufferedCommunicator();
+
+ /**
+ * @brief Build the buffers and information for the communication process.
+ *
+ *
+ * @param interface The interface that defines what indices are to be communicated.
+ */
+ template<class Data, class Interface>
+ typename enable_if<is_same<SizeOne,typename CommPolicy<Data>::IndexedTypeFlag>::value, void>::type
+ build(const Interface& interface);
+
+ /**
+ * @brief Build the buffers and information for the communication process.
+ *
+ * @param source The source in a forward send. The values will be copied from here to the send buffers.
+ * @param target The target in a forward send. The received values will be copied to here.
+ * @param interface The interface that defines what indices are to be communicated.
+ */
+ template<class Data, class Interface>
+ void build(const Data& source, const Data& target, const Interface& interface);
+
+ /**
+ * @brief Send from source to target.
+ *
+ * The template parameter GatherScatter (e.g. CopyGatherScatter) has to have a static method
+ * \code
+ * // Gather the data at index index of data
+ * static const typename CommPolicy<Data>::IndexedType>& gather(Data& data, int index);
+ *
+ * // Scatter the value at a index of data
+ * static void scatter(Data& data, typename CommPolicy<Data>::IndexedType> value,
+ * int index);
+ * \endcode
+ * in the case where CommPolicy<Data>::IndexedTypeFlag is SizeOne
+ * and
+ *
+ * \code
+ * static const typename CommPolicy<Data>::IndexedType> gather(Data& data, int index, int subindex);
+ *
+ * static void scatter(Data& data, typename CommPolicy<Data>::IndexedType> value,
+ * int index, int subindex);
+ * \endcode
+ * in the case where CommPolicy<Data>::IndexedTypeFlag is VariableSize. Here subindex is the
+ * subindex of the block at index.
+ * @warning The source and target data have to have the same layout as the ones given
+ * to the build function in case of variable size values at the indices.
+ * @param source The values will be copied from here to the send buffers.
+ * @param dest The received values will be copied to here.
+ */
+ template<class GatherScatter, class Data>
+ void forward(const Data& source, Data& dest);
+
+ /**
+ * @brief Communicate in the reverse direction, i.e. send from target to source.
+ *
+ * The template parameter GatherScatter (e.g. CopyGatherScatter) has to have a static method
+ * \code
+ * // Gather the data at index index of data
+ * static const typename CommPolicy<Data>::IndexedType>& gather(Data& data, int index);
+ *
+ * // Scatter the value at a index of data
+ * static void scatter(Data& data, typename CommPolicy<Data>::IndexedType> value,
+ * int index);
+ * \endcode
+ * in the case where CommPolicy<Data>::IndexedTypeFlag is SizeOne
+ * and
+ *
+ * \code
+ * static onst typename CommPolicy<Data>::IndexedType> gather(Data& data, int index, int subindex);
+ *
+ * static void scatter(Data& data, typename CommPolicy<Data>::IndexedType> value,
+ * int index, int subindex);
+ * \endcode
+ * in the case where CommPolicy<Data>::IndexedTypeFlag is VariableSize. Here subindex is the
+ * subindex of the block at index.
+ * @warning The source and target data have to have the same layout as the ones given
+ * to the build function in case of variable size values at the indices.
+ * @param dest The values will be copied from here to the send buffers.
+ * @param source The received values will be copied to here.
+ */
+ template<class GatherScatter, class Data>
+ void backward(Data& source, const Data& dest);
+
+ /**
+ * @brief Forward send where target and source are the same.
+ *
+ * The template parameter GatherScatter has to have a static method
+ * \code
+ * // Gather the data at index index of data
+ * static const typename CommPolicy<Data>::IndexedType>& gather(Data& data, int index);
+ *
+ * // Scatter the value at a index of data
+ * static void scatter(Data& data, typename CommPolicy<Data>::IndexedType> value,
+ * int index);
+ * \endcode
+ * in the case where CommPolicy<Data>::IndexedTypeFlag is SizeOne
+ * and
+ *
+ * \code
+ * static onst typename CommPolicy<Data>::IndexedType> gather(Data& data, int index, int subindex);
+ *
+ * static void scatter(Data& data, typename CommPolicy<Data>::IndexedType> value,
+ * int index, int subindex);
+ * \endcode
+ * in the case where CommPolicy<Data>::IndexedTypeFlag is VariableSize. Here subindex is the
+ * subindex of the block at index.
+ * @param data Source and target of the communication.
+ */
+ template<class GatherScatter, class Data>
+ void forward(Data& data);
+
+ /**
+ * @brief Backward send where target and source are the same.
+ *
+ * The template parameter GatherScatter has to have a static method
+ * \code
+ * // Gather the data at index index of data
+ * static const typename CommPolicy<Data>::IndexedType>& gather(Data& data, int index);
+ *
+ * // Scatter the value at a index of data
+ * static void scatter(Data& data, typename CommPolicy<Data>::IndexedType> value,
+ * int index);
+ * \endcode
+ * in the case where CommPolicy<Data>::IndexedTypeFlag is SizeOne
+ * and
+ *
+ * \code
+ * static onst typename CommPolicy<Data>::IndexedType> gather(Data& data, int index, int subindex);
+ *
+ * static void scatter(Data& data, typename CommPolicy<Data>::IndexedType> value,
+ * int index, int subindex);
+ * \endcode
+ * in the case where CommPolicy<Data>::IndexedTypeFlag is VariableSize. Here subindex is the
+ * subindex of the block at index.
+ * @param data Source and target of the communication.
+ */
+ template<class GatherScatter, class Data>
+ void backward(Data& data);
+
+ /**
+ * @brief Free the allocated memory (i.e. buffers and message information.
+ */
+ void free();
+
+ /**
+ * @brief Destructor.
+ */
+ ~BufferedCommunicator();
+
+ private:
+
+ /**
+ * @brief The type of the map that maps interface information to processors.
+ */
+ typedef std::map<int,std::pair<InterfaceInformation,InterfaceInformation> >
+ InterfaceMap;
+
+
+ /**
+ * @brief Functors for message size caculation
+ */
+ template<class Data, typename IndexedTypeFlag>
+ struct MessageSizeCalculator
+ {};
+
+ /**
+ * @brief Functor for message size caculation for datatypes
+ * where at each index is only one value.
+ */
+ template<class Data>
+ struct MessageSizeCalculator<Data,SizeOne>
+ {
+ /**
+ * @brief Calculate the number of values in message
+ * @param info The information about the interface corresponding
+ * to the message.
+ * @return The number of values in th message.
+ */
+ inline int operator()(const InterfaceInformation& info) const;
+ /**
+ * @brief Calculate the number of values in message
+ *
+ * @param info The information about the interface corresponding
+ * to the message.
+ * @param data ignored.
+ * @return The number of values in th message.
+ */
+ inline int operator()(const Data& data, const InterfaceInformation& info) const;
+ };
+
+ /**
+ * @brief Functor for message size caculation for datatypes
+ * where at each index can be a variable number of values.
+ */
+ template<class Data>
+ struct MessageSizeCalculator<Data,VariableSize>
+ {
+ /**
+ * @brief Calculate the number of values in message
+ *
+ * @param info The information about the interface corresponding
+ * to the message.
+ * @param data A representative of the data we send.
+ * @return The number of values in th message.
+ */
+ inline int operator()(const Data& data, const InterfaceInformation& info) const;
+ };
+
+ /**
+ * @brief Functors for message data gathering.
+ */
+ template<class Data, class GatherScatter, bool send, typename IndexedTypeFlag>
+ struct MessageGatherer
+ {};
+
+ /**
+ * @brief Functor for message data gathering for datatypes
+ * where at each index is only one value.
+ */
+ template<class Data, class GatherScatter, bool send>
+ struct MessageGatherer<Data,GatherScatter,send,SizeOne>
+ {
+ /** @brief The type of the values we send. */
+ typedef typename CommPolicy<Data>::IndexedType Type;
+
+ /**
+ * @brief The type of the functor that does the actual copying
+ * during the data Scattering.
+ */
+ typedef GatherScatter Gatherer;
+
+ enum {
+ /**
+ * @brief The communication mode
+ *
+ * True if this was a forward communication.
+ */
+ forward=send
+ };
+
+ /**
+ * @brief Copies the values to send into the buffer.
+ * @param interface The interface used in the send.
+ * @param data The data from which we copy the values.
+ * @param buffer The send buffer to copy to.
+ * @param bufferSize The size of the buffer in bytes. For checks.
+ */
+ inline void operator()(const InterfaceMap& interface, const Data& data, Type* buffer, size_t bufferSize) const;
+ };
+
+ /**
+ * @brief Functor for message data scattering for datatypes
+ * where at each index can be a variable size of values
+ */
+ template<class Data, class GatherScatter, bool send>
+ struct MessageGatherer<Data,GatherScatter,send,VariableSize>
+ {
+ /** @brief The type of the values we send. */
+ typedef typename CommPolicy<Data>::IndexedType Type;
+
+ /**
+ * @brief The type of the functor that does the actual copying
+ * during the data Scattering.
+ */
+ typedef GatherScatter Gatherer;
+
+ enum {
+ /**
+ * @brief The communication mode
+ *
+ * True if this was a forward communication.
+ */
+ forward=send
+ };
+
+ /**
+ * @brief Copies the values to send into the buffer.
+ * @param interface The interface used in the send.
+ * @param data The data from which we copy the values.
+ * @param buffer The send buffer to copy to.
+ * @param bufferSize The size of the buffer in bytes. For checks.
+ */
+ inline void operator()(const InterfaceMap& interface, const Data& data, Type* buffer, size_t bufferSize) const;
+ };
+
+ /**
+ * @brief Functors for message data scattering.
+ */
+ template<class Data, class GatherScatter, bool send, typename IndexedTypeFlag>
+ struct MessageScatterer
+ {};
+
+ /**
+ * @brief Functor for message data gathering for datatypes
+ * where at each index is only one value.
+ */
+ template<class Data, class GatherScatter, bool send>
+ struct MessageScatterer<Data,GatherScatter,send,SizeOne>
+ {
+ /** @brief The type of the values we send. */
+ typedef typename CommPolicy<Data>::IndexedType Type;
+
+ /**
+ * @brief The type of the functor that does the actual copying
+ * during the data Scattering.
+ */
+ typedef GatherScatter Scatterer;
+
+ enum {
+ /**
+ * @brief The communication mode
+ *
+ * True if this was a forward communication.
+ */
+ forward=send
+ };
+
+ /**
+ * @brief Copy the message data from the receive buffer to the data.
+ * @param interface The interface used in the send.
+ * @param data The data to which we copy the values.
+ * @param buffer The receive buffer to copy from.
+ * @param proc The rank of the process the message is from.
+ */
+ inline void operator()(const InterfaceMap& interface, Data& data, Type* buffer, const int& proc) const;
+ };
+ /**
+ * @brief Functor for message data scattering for datatypes
+ * where at each index can be a variable size of values
+ */
+ template<class Data, class GatherScatter, bool send>
+ struct MessageScatterer<Data,GatherScatter,send,VariableSize>
+ {
+ /** @brief The type of the values we send. */
+ typedef typename CommPolicy<Data>::IndexedType Type;
+
+ /**
+ * @brief The type of the functor that does the actual copying
+ * during the data Scattering.
+ */
+ typedef GatherScatter Scatterer;
+
+ enum {
+ /**
+ * @brief The communication mode
+ *
+ * True if this was a forward communication.
+ */
+ forward=send
+ };
+
+ /**
+ * @brief Copy the message data from the receive buffer to the data.
+ * @param interface The interface used in the send.
+ * @param data The data to which we copy the values.
+ * @param buffer The receive buffer to copy from.
+ * @param proc The rank of the process the message is from.
+ */
+ inline void operator()(const InterfaceMap& interface, Data& data, Type* buffer, const int& proc) const;
+ };
+
+ /**
+ * @brief Information about a message to send.
+ */
+ struct MessageInformation
+ {
+ /** @brief Constructor. */
+ MessageInformation()
+ : start_(0), size_(0)
+ {}
+
+ /**
+ * @brief Constructor.
+ * @param start The start of the message in the global buffer.
+ * Not in bytes but in number of values from the beginning of
+ * the buffer
+ * @param size The size of the message in bytes.
+ */
+ MessageInformation(size_t start, size_t size)
+ : start_(start), size_(size)
+ {}
+ /**
+ * @brief Start of the message in the buffer counted in number of value.
+ */
+ size_t start_;
+ /**
+ * @brief Number of bytes in the message.
+ */
+ size_t size_;
+ };
+
+ /**
+ * @brief Type of the map of information about the messages to send.
+ *
+ * The key is the process number to communicate with and the key is
+ * the pair of information about sending and receiving messages.
+ */
+ typedef std::map<int,std::pair<MessageInformation,MessageInformation> >
+ InformationMap;
+ /**
+ * @brief Gathered information about the messages to send.
+ */
+ InformationMap messageInformation_;
+ /**
+ * @brief Communication buffers.
+ */
+ char* buffers_[2];
+ /**
+ * @brief The size of the communication buffers
+ */
+ size_t bufferSize_[2];
+
+ enum {
+ /**
+ * @brief The tag we use for communication.
+ */
+ commTag_
+ };
+
+ /**
+ * @brief The interface we currently work with.
+ */
+ std::map<int,std::pair<InterfaceInformation,InterfaceInformation> > interfaces_;
+
+ MPI_Comm communicator_;
+
+ /**
+ * @brief Send and receive Data.
+ */
+ template<class GatherScatter, bool FORWARD, class Data>
+ void sendRecv(const Data& source, Data& target);
+
+ };
+
+#ifndef DOXYGEN
+
+ template<class V>
+ inline const void* CommPolicy<V>::getAddress(const V& v, int index)
+ {
+ return &(v[index]);
+ }
+
+ template<class V>
+ inline int CommPolicy<V>::getSize(const V& v, int index)
+ {
+ DUNE_UNUSED_PARAMETER(v);
+ DUNE_UNUSED_PARAMETER(index);
+ return 1;
+ }
+
+ template<class K, class A, int n>
+ inline const void* CommPolicy<VariableBlockVector<FieldVector<K, n>, A> >::getAddress(const Type& v, int index)
+ {
+ return &(v[index][0]);
+ }
+
+ template<class K, class A, int n>
+ inline int CommPolicy<VariableBlockVector<FieldVector<K, n>, A> >::getSize(const Type& v, int index)
+ {
+ return v[index].getsize();
+ }
+
+ template<class T>
+ inline const typename CopyGatherScatter<T>::IndexedType& CopyGatherScatter<T>::gather(const T & vec, std::size_t i)
+ {
+ return vec[i];
+ }
+
+ template<class T>
+ inline void CopyGatherScatter<T>::scatter(T& vec, const IndexedType& v, std::size_t i)
+ {
+ vec[i]=v;
+ }
+
+ template<typename T>
+ DatatypeCommunicator<T>::DatatypeCommunicator()
+ : remoteIndices_(0), created_(false)
+ {
+ requests_[0]=0;
+ requests_[1]=0;
+ }
+
+
+
+ template<typename T>
+ DatatypeCommunicator<T>::~DatatypeCommunicator()
+ {
+ free();
+ }
+
+ template<typename T>
+ template<class T1, class T2, class V>
+ inline void DatatypeCommunicator<T>::build(const RemoteIndices& remoteIndices,
+ const T1& source, V& sendData,
+ const T2& destination, V& receiveData)
+ {
+ remoteIndices_ = &remoteIndices;
+ free();
+ createDataTypes<T1,T2,V,false>(source,destination, receiveData);
+ createDataTypes<T1,T2,V,true>(source,destination, sendData);
+ createRequests<V,true>(sendData, receiveData);
+ createRequests<V,false>(receiveData, sendData);
+ created_=true;
+ }
+
+ template<typename T>
+ void DatatypeCommunicator<T>::free()
+ {
+ if(created_) {
+ delete[] requests_[0];
+ delete[] requests_[1];
+ typedef MessageTypeMap::iterator iterator;
+ typedef MessageTypeMap::const_iterator const_iterator;
+
+ const const_iterator end=messageTypes.end();
+
+ for(iterator process = messageTypes.begin(); process != end; ++process) {
+ MPI_Datatype *type = &(process->second.first);
+ int finalized=0;
+#if MPI_2
+ MPI_Finalized(&finalized);
+#endif
+ if(*type!=MPI_DATATYPE_NULL && !finalized)
+ MPI_Type_free(type);
+ type = &(process->second.second);
+ if(*type!=MPI_DATATYPE_NULL && !finalized)
+ MPI_Type_free(type);
+ }
+ messageTypes.clear();
+ created_=false;
+ }
+
+ }
+
+ template<typename T>
+ template<class T1, class T2, class V, bool send>
+ void DatatypeCommunicator<T>::createDataTypes(const T1& sourceFlags, const T2& destFlags, V& data)
+ {
+
+ MPIDatatypeInformation<V> dataInfo(data);
+ this->template buildInterface<RemoteIndices,T1,T2,MPIDatatypeInformation<V>,send>(*remoteIndices_,sourceFlags, destFlags, dataInfo);
+
+ typedef typename RemoteIndices::RemoteIndexMap::const_iterator const_iterator;
+ const const_iterator end=this->remoteIndices_->end();
+
+ // Allocate MPI_Datatypes and deallocate memory for the type construction.
+ for(const_iterator process=this->remoteIndices_->begin(); process != end; ++process) {
+ IndexedTypeInformation& info=dataInfo.information_[process->first];
+ // Shift the displacement
+ MPI_Aint base;
+ MPI_Address(const_cast<void *>(CommPolicy<V>::getAddress(data, 0)), &base);
+
+ for(int i=0; i< info.elements; i++) {
+ info.displ[i]-=base;
+ }
+
+ // Create data type
+ MPI_Datatype* type = &( send ? messageTypes[process->first].first : messageTypes[process->first].second);
+ MPI_Type_hindexed(info.elements, info.length, info.displ,
+ MPITraits<typename CommPolicy<V>::IndexedType>::getType(),
+ type);
+ MPI_Type_commit(type);
+ // Deallocate memory
+ info.free();
+ }
+ }
+
+ template<typename T>
+ template<class V, bool createForward>
+ void DatatypeCommunicator<T>::createRequests(V& sendData, V& receiveData)
+ {
+ typedef std::map<int,std::pair<MPI_Datatype,MPI_Datatype> >::const_iterator MapIterator;
+ int rank;
+ static int index = createForward ? 1 : 0;
+ int noMessages = messageTypes.size();
+ // allocate request handles
+ requests_[index] = new MPI_Request[2*noMessages];
+ const MapIterator end = messageTypes.end();
+ int request=0;
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+ // Set up the requests for receiving first
+ for(MapIterator process = messageTypes.begin(); process != end;
+ ++process, ++request) {
+ MPI_Datatype type = createForward ? process->second.second : process->second.first;
+ void* address = const_cast<void*>(CommPolicy<V>::getAddress(receiveData,0));
+ MPI_Recv_init(address, 1, type, process->first, commTag_, this->remoteIndices_->communicator(), requests_[index]+request);
+ }
+
+ // And now the send requests
+
+ for(MapIterator process = messageTypes.begin(); process != end;
+ ++process, ++request) {
+ MPI_Datatype type = createForward ? process->second.first : process->second.second;
+ void* address = const_cast<void*>(CommPolicy<V>::getAddress(sendData, 0));
+ MPI_Ssend_init(address, 1, type, process->first, commTag_, this->remoteIndices_->communicator(), requests_[index]+request);
+ }
+ }
+
+ template<typename T>
+ void DatatypeCommunicator<T>::forward()
+ {
+ sendRecv(requests_[1]);
+ }
+
+ template<typename T>
+ void DatatypeCommunicator<T>::backward()
+ {
+ sendRecv(requests_[0]);
+ }
+
+ template<typename T>
+ void DatatypeCommunicator<T>::sendRecv(MPI_Request* requests)
+ {
+ int noMessages = messageTypes.size();
+ // Start the receive calls first
+ MPI_Startall(noMessages, requests);
+ // Now the send calls
+ MPI_Startall(noMessages, requests+noMessages);
+
+ // Wait for completion of the communication send first then receive
+ MPI_Status* status=new MPI_Status[2*noMessages];
+ for(int i=0; i<2*noMessages; i++)
+ status[i].MPI_ERROR=MPI_SUCCESS;
+
+ int send = MPI_Waitall(noMessages, requests+noMessages, status+noMessages);
+ int receive = MPI_Waitall(noMessages, requests, status);
+
+ // Error checks
+ int success=1, globalSuccess=0;
+ if(send==MPI_ERR_IN_STATUS) {
+ int rank;
+ MPI_Comm_rank(this->remoteIndices_->communicator(), &rank);
+ std::cerr<<rank<<": Error in sending :"<<std::endl;
+ // Search for the error
+ for(int i=noMessages; i< 2*noMessages; i++)
+ if(status[i].MPI_ERROR!=MPI_SUCCESS) {
+ char message[300];
+ int messageLength;
+ MPI_Error_string(status[i].MPI_ERROR, message, &messageLength);
+ std::cerr<<" source="<<status[i].MPI_SOURCE<<" message: ";
+ for(int i=0; i< messageLength; i++)
+ std::cout<<message[i];
+ }
+ std::cerr<<std::endl;
+ success=0;
+ }
+
+ if(receive==MPI_ERR_IN_STATUS) {
+ int rank;
+ MPI_Comm_rank(this->remoteIndices_->communicator(), &rank);
+ std::cerr<<rank<<": Error in receiving!"<<std::endl;
+ // Search for the error
+ for(int i=0; i< noMessages; i++)
+ if(status[i].MPI_ERROR!=MPI_SUCCESS) {
+ char message[300];
+ int messageLength;
+ MPI_Error_string(status[i].MPI_ERROR, message, &messageLength);
+ std::cerr<<" source="<<status[i].MPI_SOURCE<<" message: ";
+ for(int i=0; i< messageLength; i++)
+ std::cerr<<message[i];
+ }
+ std::cerr<<std::endl;
+ success=0;
+ }
+
+ MPI_Allreduce(&success, &globalSuccess, 1, MPI_INT, MPI_MIN, this->remoteIndices_->communicator());
+
+ delete[] status;
+
+ if(!globalSuccess)
+ DUNE_THROW(CommunicationError, "A communication error occurred!");
+
+ }
+
+ inline BufferedCommunicator::BufferedCommunicator()
+ {
+ buffers_[0]=0;
+ buffers_[1]=0;
+ bufferSize_[0]=0;
+ bufferSize_[1]=0;
+ }
+
+ template<class Data, class Interface>
+ typename enable_if<is_same<SizeOne, typename CommPolicy<Data>::IndexedTypeFlag>::value, void>::type
+ BufferedCommunicator::build(const Interface& interface)
+ {
+ interfaces_=interface.interfaces();
+ communicator_=interface.communicator();
+ typedef typename std::map<int,std::pair<InterfaceInformation,InterfaceInformation> >
+ ::const_iterator const_iterator;
+ typedef typename CommPolicy<Data>::IndexedTypeFlag Flag;
+ const const_iterator end = interfaces_.end();
+ int lrank;
+ MPI_Comm_rank(communicator_, &lrank);
+
+ bufferSize_[0]=0;
+ bufferSize_[1]=0;
+
+ for(const_iterator interfacePair = interfaces_.begin();
+ interfacePair != end; ++interfacePair) {
+ int noSend = MessageSizeCalculator<Data,Flag>() (interfacePair->second.first);
+ int noRecv = MessageSizeCalculator<Data,Flag>() (interfacePair->second.second);
+ if (noSend + noRecv > 0)
+ messageInformation_.insert(std::make_pair(interfacePair->first,
+ std::make_pair(MessageInformation(bufferSize_[0],
+ noSend*sizeof(typename CommPolicy<Data>::IndexedType)),
+ MessageInformation(bufferSize_[1],
+ noRecv*sizeof(typename CommPolicy<Data>::IndexedType)))));
+ bufferSize_[0] += noSend;
+ bufferSize_[1] += noRecv;
+ }
+
+ // allocate the buffers
+ bufferSize_[0] *= sizeof(typename CommPolicy<Data>::IndexedType);
+ bufferSize_[1] *= sizeof(typename CommPolicy<Data>::IndexedType);
+
+ buffers_[0] = new char[bufferSize_[0]];
+ buffers_[1] = new char[bufferSize_[1]];
+ }
+
+ template<class Data, class Interface>
+ void BufferedCommunicator::build(const Data& source, const Data& dest, const Interface& interface)
+ {
+
+ interfaces_=interface.interfaces();
+ communicator_=interface.communicator();
+ typedef typename std::map<int,std::pair<InterfaceInformation,InterfaceInformation> >
+ ::const_iterator const_iterator;
+ typedef typename CommPolicy<Data>::IndexedTypeFlag Flag;
+ const const_iterator end = interfaces_.end();
+
+ bufferSize_[0]=0;
+ bufferSize_[1]=0;
+
+ for(const_iterator interfacePair = interfaces_.begin();
+ interfacePair != end; ++interfacePair) {
+ int noSend = MessageSizeCalculator<Data,Flag>() (source, interfacePair->second.first);
+ int noRecv = MessageSizeCalculator<Data,Flag>() (dest, interfacePair->second.second);
+ if (noSend + noRecv > 0)
+ messageInformation_.insert(std::make_pair(interfacePair->first,
+ std::make_pair(MessageInformation(bufferSize_[0],
+ noSend*sizeof(typename CommPolicy<Data>::IndexedType)),
+ MessageInformation(bufferSize_[1],
+ noRecv*sizeof(typename CommPolicy<Data>::IndexedType)))));
+ bufferSize_[0] += noSend;
+ bufferSize_[1] += noRecv;
+ }
+
+ bufferSize_[0] *= sizeof(typename CommPolicy<Data>::IndexedType);
+ bufferSize_[1] *= sizeof(typename CommPolicy<Data>::IndexedType);
+ // allocate the buffers
+ buffers_[0] = new char[bufferSize_[0]];
+ buffers_[1] = new char[bufferSize_[1]];
+ }
+
+ inline void BufferedCommunicator::free()
+ {
+ messageInformation_.clear();
+ if(buffers_[0])
+ delete[] buffers_[0];
+
+ if(buffers_[1])
+ delete[] buffers_[1];
+ buffers_[0]=buffers_[1]=0;
+ }
+
+ inline BufferedCommunicator::~BufferedCommunicator()
+ {
+ free();
+ }
+
+ template<class Data>
+ inline int BufferedCommunicator::MessageSizeCalculator<Data,SizeOne>::operator()
+ (const InterfaceInformation& info) const
+ {
+ return info.size();
+ }
+
+
+ template<class Data>
+ inline int BufferedCommunicator::MessageSizeCalculator<Data,SizeOne>::operator()
+ (const Data&, const InterfaceInformation& info) const
+ {
+ return operator()(info);
+ }
+
+
+ template<class Data>
+ inline int BufferedCommunicator::MessageSizeCalculator<Data, VariableSize>::operator()
+ (const Data& data, const InterfaceInformation& info) const
+ {
+ int entries=0;
+
+ for(size_t i=0; i < info.size(); i++)
+ entries += CommPolicy<Data>::getSize(data,info[i]);
+
+ return entries;
+ }
+
+
+ template<class Data, class GatherScatter, bool FORWARD>
+ inline void BufferedCommunicator::MessageGatherer<Data,GatherScatter,FORWARD,VariableSize>::operator()(const InterfaceMap& interfaces,const Data& data, Type* buffer, size_t bufferSize) const
+ {
+ typedef typename InterfaceMap::const_iterator
+ const_iterator;
+
+ int rank;
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+ const const_iterator end = interfaces.end();
+ size_t index=0;
+
+ for(const_iterator interfacePair = interfaces.begin();
+ interfacePair != end; ++interfacePair) {
+ int size = forward ? interfacePair->second.first.size() :
+ interfacePair->second.second.size();
+
+ for(int i=0; i < size; i++) {
+ int local = forward ? interfacePair->second.first[i] :
+ interfacePair->second.second[i];
+ for(std::size_t j=0; j < CommPolicy<Data>::getSize(data, local); j++, index++) {
+
+#ifdef DUNE_ISTL_WITH_CHECKING
+ assert(bufferSize>=(index+1)*sizeof(typename CommPolicy<Data>::IndexedType));
+#endif
+ buffer[index]=GatherScatter::gather(data, local, j);
+ }
+
+ }
+ }
+
+ }
+
+
+ template<class Data, class GatherScatter, bool FORWARD>
+ inline void BufferedCommunicator::MessageGatherer<Data,GatherScatter,FORWARD,SizeOne>::operator()(const InterfaceMap& interfaces, const Data& data, Type* buffer, size_t bufferSize) const
+ {
+ DUNE_UNUSED_PARAMETER(bufferSize);
+ typedef typename InterfaceMap::const_iterator
+ const_iterator;
+ const const_iterator end = interfaces.end();
+ size_t index = 0;
+
+ int rank;
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+ for(const_iterator interfacePair = interfaces.begin();
+ interfacePair != end; ++interfacePair) {
+ size_t size = FORWARD ? interfacePair->second.first.size() :
+ interfacePair->second.second.size();
+
+ for(size_t i=0; i < size; i++) {
+
+#ifdef DUNE_ISTL_WITH_CHECKING
+ assert(bufferSize>=(index+1)*sizeof(typename CommPolicy<Data>::IndexedType));
+#endif
+
+ buffer[index++] = GatherScatter::gather(data, FORWARD ? interfacePair->second.first[i] :
+ interfacePair->second.second[i]);
+ }
+ }
+
+ }
+
+
+ template<class Data, class GatherScatter, bool FORWARD>
+ inline void BufferedCommunicator::MessageScatterer<Data,GatherScatter,FORWARD,VariableSize>::operator()(const InterfaceMap& interfaces, Data& data, Type* buffer, const int& proc) const
+ {
+ typedef typename InterfaceMap::value_type::second_type::first_type Information;
+ const typename InterfaceMap::const_iterator infoPair = interfaces.find(proc);
+
+ assert(infoPair!=interfaces.end());
+
+ const Information& info = FORWARD ? infoPair->second.second :
+ infoPair->second.first;
+
+ for(size_t i=0, index=0; i < info.size(); i++) {
+ for(size_t j=0; j < CommPolicy<Data>::getSize(data, info[i]); j++)
+ GatherScatter::scatter(data, buffer[index++], info[i], j);
+ }
+ }
+
+
+ template<class Data, class GatherScatter, bool FORWARD>
+ inline void BufferedCommunicator::MessageScatterer<Data,GatherScatter,FORWARD,SizeOne>::operator()(const InterfaceMap& interfaces, Data& data, Type* buffer, const int& proc) const
+ {
+ typedef typename InterfaceMap::value_type::second_type::first_type Information;
+ const typename InterfaceMap::const_iterator infoPair = interfaces.find(proc);
+
+ assert(infoPair!=interfaces.end());
+
+ const Information& info = FORWARD ? infoPair->second.second :
+ infoPair->second.first;
+
+ for(size_t i=0; i < info.size(); i++) {
+ GatherScatter::scatter(data, buffer[i], info[i]);
+ }
+ }
+
+
+ template<class GatherScatter,class Data>
+ void BufferedCommunicator::forward(Data& data)
+ {
+ this->template sendRecv<GatherScatter,true>(data, data);
+ }
+
+
+ template<class GatherScatter, class Data>
+ void BufferedCommunicator::backward(Data& data)
+ {
+ this->template sendRecv<GatherScatter,false>(data, data);
+ }
+
+
+ template<class GatherScatter, class Data>
+ void BufferedCommunicator::forward(const Data& source, Data& dest)
+ {
+ this->template sendRecv<GatherScatter,true>(source, dest);
+ }
+
+
+ template<class GatherScatter, class Data>
+ void BufferedCommunicator::backward(Data& source, const Data& dest)
+ {
+ this->template sendRecv<GatherScatter,false>(dest, source);
+ }
+
+
+ template<class GatherScatter, bool FORWARD, class Data>
+ void BufferedCommunicator::sendRecv(const Data& source, Data& dest)
+ {
+ int rank, lrank;
+
+ MPI_Comm_rank(MPI_COMM_WORLD,&rank);
+ MPI_Comm_rank(MPI_COMM_WORLD,&lrank);
+
+ typedef typename CommPolicy<Data>::IndexedType Type;
+ Type *sendBuffer, *recvBuffer;
+ size_t sendBufferSize;
+#ifndef NDEBUG
+ size_t recvBufferSize;
+#endif
+
+ if(FORWARD) {
+ sendBuffer = reinterpret_cast<Type*>(buffers_[0]);
+ sendBufferSize = bufferSize_[0];
+ recvBuffer = reinterpret_cast<Type*>(buffers_[1]);
+#ifndef NDEBUG
+ recvBufferSize = bufferSize_[1];
+#endif
+ }else{
+ sendBuffer = reinterpret_cast<Type*>(buffers_[1]);
+ sendBufferSize = bufferSize_[1];
+ recvBuffer = reinterpret_cast<Type*>(buffers_[0]);
+#ifndef NDEBUG
+ recvBufferSize = bufferSize_[0];
+#endif
+ }
+ typedef typename CommPolicy<Data>::IndexedTypeFlag Flag;
+
+ MessageGatherer<Data,GatherScatter,FORWARD,Flag>() (interfaces_, source, sendBuffer, sendBufferSize);
+
+ MPI_Request* sendRequests = new MPI_Request[messageInformation_.size()];
+ MPI_Request* recvRequests = new MPI_Request[messageInformation_.size()];
+
+ // Setup receive first
+ typedef typename InformationMap::const_iterator const_iterator;
+
+ const const_iterator end = messageInformation_.end();
+ size_t i=0;
+ int* processMap = new int[messageInformation_.size()];
+
+ for(const_iterator info = messageInformation_.begin(); info != end; ++info, ++i) {
+ processMap[i]=info->first;
+ if(FORWARD) {
+ assert(info->second.second.start_*sizeof(typename CommPolicy<Data>::IndexedType)+info->second.second.size_ <= recvBufferSize );
+ Dune::dvverb<<rank<<": receiving "<<info->second.second.size_<<" from "<<info->first<<std::endl;
+ MPI_Irecv(recvBuffer+info->second.second.start_, info->second.second.size_,
+ MPI_BYTE, info->first, commTag_, communicator_,
+ recvRequests+i);
+ }else{
+ assert(info->second.first.start_*sizeof(typename CommPolicy<Data>::IndexedType)+info->second.first.size_ <= recvBufferSize );
+ Dune::dvverb<<rank<<": receiving "<<info->second.first.size_<<" to "<<info->first<<std::endl;
+ MPI_Irecv(recvBuffer+info->second.first.start_, info->second.first.size_,
+ MPI_BYTE, info->first, commTag_, communicator_,
+ recvRequests+i);
+ }
+ }
+
+ // now the send requests
+ i=0;
+ for(const_iterator info = messageInformation_.begin(); info != end; ++info, ++i)
+ if(FORWARD) {
+ assert(info->second.second.start_*sizeof(typename CommPolicy<Data>::IndexedType)+info->second.second.size_ <= recvBufferSize );
+ Dune::dvverb<<rank<<": sending "<<info->second.first.size_<<" to "<<info->first<<std::endl;
+ assert(info->second.first.start_*sizeof(typename CommPolicy<Data>::IndexedType)+info->second.first.size_ <= sendBufferSize );
+ MPI_Issend(sendBuffer+info->second.first.start_, info->second.first.size_,
+ MPI_BYTE, info->first, commTag_, communicator_,
+ sendRequests+i);
+ }else{
+ assert(info->second.second.start_*sizeof(typename CommPolicy<Data>::IndexedType)+info->second.second.size_ <= sendBufferSize );
+ Dune::dvverb<<rank<<": sending "<<info->second.second.size_<<" to "<<info->first<<std::endl;
+ MPI_Issend(sendBuffer+info->second.second.start_, info->second.second.size_,
+ MPI_BYTE, info->first, commTag_, communicator_,
+ sendRequests+i);
+ }
+
+ // Wait for completion of receive and immediately start scatter
+ i=0;
+ //int success = 1;
+ int finished = MPI_UNDEFINED;
+ MPI_Status status; //[messageInformation_.size()];
+ //MPI_Waitall(messageInformation_.size(), recvRequests, status);
+
+ for(i=0; i< messageInformation_.size(); i++) {
+ status.MPI_ERROR=MPI_SUCCESS;
+ MPI_Waitany(messageInformation_.size(), recvRequests, &finished, &status);
+ assert(finished != MPI_UNDEFINED);
+
+ if(status.MPI_ERROR==MPI_SUCCESS) {
+ int& proc = processMap[finished];
+ typename InformationMap::const_iterator infoIter = messageInformation_.find(proc);
+ assert(infoIter != messageInformation_.end());
+
+ MessageInformation info = (FORWARD) ? infoIter->second.second : infoIter->second.first;
+ assert(info.start_+info.size_ <= recvBufferSize);
+
+ MessageScatterer<Data,GatherScatter,FORWARD,Flag>() (interfaces_, dest, recvBuffer+info.start_, proc);
+ }else{
+ std::cerr<<rank<<": MPI_Error occurred while receiving message from "<<processMap[finished]<<std::endl;
+ //success=0;
+ }
+ }
+
+ MPI_Status recvStatus;
+
+ // Wait for completion of sends
+ for(i=0; i< messageInformation_.size(); i++)
+ if(MPI_SUCCESS!=MPI_Wait(sendRequests+i, &recvStatus)) {
+ std::cerr<<rank<<": MPI_Error occurred while sending message to "<<processMap[finished]<<std::endl;
+ //success=0;
+ }
+ /*
+ int globalSuccess;
+ MPI_Allreduce(&success, &globalSuccess, 1, MPI_INT, MPI_MIN, interface_->communicator());
+
+ if(!globalSuccess)
+ DUNE_THROW(CommunicationError, "A communication error occurred!");
+ */
+ delete[] processMap;
+ delete[] sendRequests;
+ delete[] recvRequests;
+
+ }
+
+#endif // DOXYGEN
+
+ /** @} */
+}
+
+#endif
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+#ifndef DUNE_INDEXSET_HH
+#define DUNE_INDEXSET_HH
+
+#include <algorithm>
+#include <dune/common/arraylist.hh>
+#include <dune/common/exceptions.hh>
+#include <dune/common/unused.hh>
+#include <iostream>
+
+#include "localindex.hh"
+
+#include <stdint.h> // for uint32_t
+
+namespace Dune
+{
+ /** @addtogroup Common_Parallel
+ *
+ * @{
+ */
+ /**
+ * @file
+ * @brief Provides a map between global and local indices.
+ * @author Markus Blatt
+ */
+ // forward declarations
+
+ template<class TG, class TL>
+ class IndexPair;
+
+ /**
+ * @brief Print an index pair.
+ * @param os The outputstream to print to.
+ * @param pair The index pair to print.
+ */
+ template<class TG, class TL>
+ std::ostream& operator<<(std::ostream& os, const IndexPair<TG,TL>& pair);
+
+ template<class TG, class TL>
+ bool operator==(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
+
+ template<class TG, class TL>
+ bool operator!=(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
+
+ template<class TG, class TL>
+ bool operator<(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
+
+ template<class TG, class TL>
+ bool operator>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
+
+ template<class TG, class TL>
+ bool operator<=(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
+
+ template<class TG, class TL>
+ bool operator >=(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
+
+ template<class TG, class TL>
+ bool operator==(const IndexPair<TG,TL>&, const TG&);
+
+ template<class TG, class TL>
+ bool operator!=(const IndexPair<TG,TL>&, const TG&);
+
+ template<class TG, class TL>
+ bool operator<(const IndexPair<TG,TL>&, const TG&);
+
+ template<class TG, class TL>
+ bool operator>(const IndexPair<TG,TL>&, const TG&);
+
+ template<class TG, class TL>
+ bool operator<=(const IndexPair<TG,TL>&, const TG&);
+
+ template<class TG, class TL>
+ bool operator >=(const IndexPair<TG,TL>&, const TG&);
+
+ template<typename T>
+ struct MPITraits;
+
+ /**
+ * @brief A pair consisting of a global and local index.
+ */
+ template<class TG, class TL>
+ class IndexPair
+ {
+ friend std::ostream& operator<<<>(std::ostream&, const IndexPair<TG,TL>&);
+ friend bool operator==<>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
+ friend bool operator!=<>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
+ friend bool operator< <>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
+ friend bool operator><>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
+ friend bool operator<=<>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
+ friend bool operator>=<>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
+ friend bool operator==<>(const IndexPair<TG,TL>&, const TG &);
+ friend bool operator!=<>(const IndexPair<TG,TL>&, const TG &);
+ friend bool operator< <>(const IndexPair<TG,TL>&, const TG &);
+ friend bool operator> <>(const IndexPair<TG,TL>&, const TG &);
+ friend bool operator<=<>(const IndexPair<TG,TL>&, const TG &);
+ friend bool operator>=<>(const IndexPair<TG,TL>&, const TG &);
+ friend struct MPITraits<IndexPair<TG,TL> >;
+
+ public:
+ /**
+ * @brief the type of the global index.
+ *
+ * This type has to provide at least a operator< for sorting.
+ */
+ typedef TG GlobalIndex;
+
+ /**
+ * @brief the type of the local index.
+ *
+ * This class to provide the following functions:
+ * \code
+ * LocalIndex operator=(int);
+ * operator int() const;
+ * LocalIndexState state() const;
+ * void setState(LocalIndexState);
+ * \endcode
+ */
+ typedef TL LocalIndex;
+
+ /**
+ * @brief Constructs a new Pair.
+ *
+ * @param global The global index.
+ * @param local The local index.
+ */
+ IndexPair(const GlobalIndex& global, const LocalIndex& local);
+
+ /**
+ * @brief Construct a new Pair.
+ */
+ IndexPair();
+ /**
+ * @brief Constructs a new Pair.
+ *
+ * The local index will be 0.
+ * @param global The global index.
+ */
+ IndexPair(const GlobalIndex& global);
+
+ /**
+ * @brief Get the global index.
+ *
+ * @return The global index.
+ */
+ inline const GlobalIndex& global() const;
+
+ /**
+ * @brief Get the local index.
+ *
+ * @return The local index.
+ */
+ inline LocalIndex& local();
+
+ /**
+ * @brief Get the local index.
+ *
+ * @return The local index.
+ */
+ inline const LocalIndex& local() const;
+
+ /**
+ * @brief Set the local index.
+ *
+ * @param index The index to set it to.
+ */
+ inline void setLocal(int index);
+ private:
+ /** @brief The global index. */
+ GlobalIndex global_;
+ /** @brief The local index. */
+ LocalIndex local_;
+ };
+
+ /**
+ * @brief The states the index set can be in.
+ * @see ParallelIndexSet::state_
+ */
+ enum ParallelIndexSetState
+ {
+ /**
+ * @brief The default mode.
+ * Indicates that the index set is ready to be used.
+ */
+ GROUND,
+ /**
+ * @brief Indicates that the index set is currently being resized.
+ */
+ RESIZE
+ /**
+ * @brief Indicates that all previously deleted indices are now deleted.
+ *
+ CLEAN,
+ **
+ * @brief Indicates that the index set is currently being reordered.
+ *
+ REORDER
+ */
+ };
+
+ /**
+ * @brief Exception indicating that the index set is not in the expected state.
+ */
+ class InvalidIndexSetState : public Exception {};
+
+ // Forward declaration
+ template<class I> class GlobalLookupIndexSet;
+
+ /**
+ * @brief Manager class for the mapping between local indices and globally unique indices.
+ *
+ * The mapping is between a globally unique id and local index. The local index is consecutive
+ * and non persistent while the global id might not be consecutive but definitely is persistent.
+ */
+ template<typename TG, typename TL, int N=100>
+ class ParallelIndexSet
+ {
+ friend class GlobalLookupIndexSet<ParallelIndexSet<TG,TL,N> >;
+
+ public:
+ /**
+ * @brief the type of the global index.
+ * This type has to provide at least a operator< for sorting.
+ */
+ typedef TG GlobalIndex;
+
+ /**
+ * @brief The type of the local index, e.g. ParallelLocalIndex.
+ *
+ * This class to provide the following functions:
+ * \code
+ * LocalIndex operator=(int);
+ * operator int() const;
+ * LocalIndexState state() const;
+ * void setState(LocalIndexState);
+ * \endcode
+ */
+ typedef TL LocalIndex;
+
+ /**
+ * @brief The type of the pair stored.
+ */
+ typedef Dune::IndexPair<GlobalIndex,LocalIndex> IndexPair;
+
+ enum {
+ /**
+ * @brief The size of the individual arrays in the underlying ArrayList.
+ *
+ * The default value is 100.
+ * @see ArrayList::size
+ */
+ arraySize= (N>0) ? N : 1
+ };
+
+ /** @brief The iterator over the pairs. */
+ class iterator :
+ public ArrayList<IndexPair,N>::iterator
+ {
+ typedef typename ArrayList<IndexPair,N>::iterator
+ Father;
+ friend class ParallelIndexSet<GlobalIndex,LocalIndex,N>;
+ public:
+ iterator(ParallelIndexSet<TG,TL,N>& indexSet, const Father& father)
+ : Father(father), indexSet_(&indexSet)
+ {}
+
+ iterator(const iterator& other)
+ : Father(other), indexSet_(other.indexSet_)
+ {}
+
+ iterator& operator==(const iterator& other)
+ {
+ Father::operator==(other);
+ indexSet_ = other.indexSet_;
+ }
+
+ private:
+ /**
+ * @brief Mark the index as deleted.
+ *
+ * The deleted flag will be set in the local index.
+ * The index will be removed in the endResize method of the
+ * index set.
+ */
+ inline void markAsDeleted() const throw(InvalidIndexSetState)
+ {
+#ifndef NDEBUG
+ if(indexSet_->state_ != RESIZE)
+ DUNE_THROW(InvalidIndexSetState, "Indices can only be removed "
+ <<"while in RESIZE state!");
+#endif
+ Father::operator*().local().setState(DELETED);
+ }
+
+ /** @brief The index set we are an iterator of. */
+ ParallelIndexSet<TG,TL,N>* indexSet_;
+
+ };
+
+
+
+ /** @brief The constant iterator over the pairs. */
+ typedef typename
+ ArrayList<IndexPair,N>::const_iterator
+ const_iterator;
+
+ /**
+ * @brief Constructor.
+ */
+ ParallelIndexSet();
+
+ /**
+ * @brief Get the state the index set is in.
+ * @return The state of the index set.
+ */
+ inline const ParallelIndexSetState& state()
+ {
+ return state_;
+ }
+
+ /**
+ * @brief Indicate that the index set is to be resized.
+ * @exception InvalidState If index set was not in
+ * ParallelIndexSetState::GROUND mode.
+ */
+ void beginResize() throw(InvalidIndexSetState);
+
+ /**
+ * @brief Add an new index to the set.
+ *
+ * The local index is created by the default constructor.
+ * @param global The globally unique id of the index.
+ * @exception InvalidState If index set is not in
+ * ParallelIndexSetState::RESIZE mode.
+ */
+ inline void add(const GlobalIndex& global) throw(InvalidIndexSetState);
+
+ /**
+ * @brief Add an new index to the set.
+ *
+ * @param global The globally unique id of the index.
+ * @param local The local index.
+ * @exception InvalidState If index set is not in
+ * ParallelIndexSetState::RESIZE mode.
+ */
+ inline void add(const GlobalIndex& global, const LocalIndex& local)
+ throw(InvalidIndexSetState);
+
+ /**
+ * @brief Mark an index as deleted.
+ *
+ * The index will be deleted during endResize().
+ * @param position An iterator at the position we want to delete.
+ * @exception InvalidState If index set is not in ParallelIndexSetState::RESIZE mode.
+ */
+ inline void markAsDeleted(const iterator& position)
+ throw(InvalidIndexSetState);
+
+ /**
+ * @brief Indicate that the resizing finishes.
+ *
+ * @warning Invalidates all pointers stored to the elements of this index set.
+ * The local indices will be ordered
+ * according to the global indices:
+ * Let \f$(g_i,l_i)_{i=0}^N \f$ be the set of all indices then \f$l_i < l_j\f$
+ * if and
+ * only if \f$g_i < g_j\f$ for arbitrary \f$i \neq j\f$.
+ * @exception InvalidState If index set was not in
+ * ParallelIndexSetState::RESIZE mode.
+ */
+ void endResize() throw(InvalidIndexSetState);
+
+ /**
+ * @brief Find the index pair with a specific global id.
+ *
+ * This starts a binary search for the entry and therefor has complexity
+ * N log(N).
+ * @param global The globally unique id of the pair.
+ * @return The pair of indices for the id.
+ * @warning If the global index is not in the set a wrong or even a
+ * null reference might be returned. To be save use the throwing alternative at.
+ */
+ inline IndexPair&
+ operator[](const GlobalIndex& global);
+
+ /**
+ * @brief Find the index pair with a specific global id.
+ *
+ * This starts a binary search for the entry and therefor has complexity
+ * N log(N).
+ * @param global The globally unique id of the pair.
+ * @return The pair of indices for the id.
+ * @exception RangeError Thrown if the global id is not known.
+ */
+ inline IndexPair&
+ at(const GlobalIndex& global);
+
+ /**
+ * @brief Find the index pair with a specific global id.
+ *
+ * This starts a binary search for the entry and therefor has complexity
+ * N log(N).
+ * @param global The globally unique id of the pair.
+ * @return The pair of indices for the id.
+ * @warning If the global index is not in the set a wrong or even a
+ * null reference might be returned. To be save use the throwing alternative at.
+ */
+ inline const IndexPair&
+ operator[](const GlobalIndex& global) const;
+
+ /**
+ * @brief Find the index pair with a specific global id.
+ *
+ * This starts a binary search for the entry and therefor has complexity
+ * N log(N).
+ * @param global The globally unique id of the pair.
+ * @return The pair of indices for the id.
+ * @exception RangeError Thrown if the global id is not known.
+ */
+ inline const IndexPair&
+ at(const GlobalIndex& global) const;
+
+ /**
+ * @brief Get an iterator over the indices positioned at the first index.
+ * @return Iterator over the local indices.
+ */
+ inline iterator begin();
+
+ /**
+ * @brief Get an iterator over the indices positioned after the last index.
+ * @return Iterator over the local indices.
+ */
+ inline iterator end();
+
+ /**
+ * @brief Get an iterator over the indices positioned at the first index.
+ * @return Iterator over the local indices.
+ */
+ inline const_iterator begin() const;
+
+ /**
+ * @brief Get an iterator over the indices positioned after the last index.
+ * @return Iterator over the local indices.
+ */
+ inline const_iterator end() const;
+
+ /**
+ * @brief Renumbers the local index numbers.
+ *
+ * After this function returns the indices are
+ * consecutively numbered beginning from 0. Let
+ * $(g_i,l_i)$, $(g_j,l_j)$ be two arbituary index
+ * pairs with $g_i<g_j$ then after renumbering
+ * $l_i<l_j$ will hold.
+ */
+ inline void renumberLocal();
+
+ /**
+ * @brief Get the internal sequence number.
+ *
+ * Is initially 0 is incremented for each resize.
+ * @return The sequence number.
+ */
+ inline int seqNo() const;
+
+ /**
+ * @brief Get the total number (public and nonpublic) indices.
+ * @return The total number (public and nonpublic) indices.
+ */
+ inline size_t size() const;
+
+ private:
+ /** @brief The index pairs. */
+ ArrayList<IndexPair,N> localIndices_;
+ /** @brief The new indices for the RESIZE state. */
+ ArrayList<IndexPair,N> newIndices_;
+ /** @brief The state of the index set. */
+ ParallelIndexSetState state_;
+ /** @brief Number to keep track of the number of resizes. */
+ int seqNo_;
+ /** @brief Whether entries were deleted in resize mode. */
+ bool deletedEntries_;
+ /**
+ * @brief Merges the _localIndices and newIndices arrays and creates a new
+ * localIndices array.
+ */
+ inline void merge();
+ };
+
+
+ /**
+ * @brief Print an index set.
+ * @param os The outputstream to print to.
+ * @param indexSet The index set to print.
+ */
+ template<class TG, class TL, int N>
+ std::ostream& operator<<(std::ostream& os, const ParallelIndexSet<TG,TL,N>& indexSet);
+
+ /**
+ * @brief Decorates an index set with the possibility to find a global index
+ * that is mapped to a specific local.
+ *
+ */
+ template<class I>
+ class GlobalLookupIndexSet
+ {
+ public:
+ /**
+ * @brief The type of the index set.
+ */
+ typedef I ParallelIndexSet;
+
+ /**
+ * @brief The type of the local index.
+ */
+ typedef typename ParallelIndexSet::LocalIndex LocalIndex;
+
+ /**
+ * @brief The type of the global index.
+ */
+ typedef typename ParallelIndexSet::GlobalIndex GlobalIndex;
+
+ /**
+ * @brief The iterator over the index pairs.
+ */
+ typedef typename ParallelIndexSet::const_iterator const_iterator;
+
+ typedef Dune::IndexPair<typename I::GlobalIndex, typename I::LocalIndex> IndexPair;
+
+ /**
+ * @brief Constructor.
+ * @param indexset The index set we want to be able to lookup the corresponding
+ * global index of a local index.
+ * @param size The number of indices present, i.e. one more than the maximum local index.
+ */
+ GlobalLookupIndexSet(const ParallelIndexSet& indexset, std::size_t size);
+
+ /**
+ * @brief Constructor.
+ * @param indexset The index set we want to be able to lookup the corresponding
+ * global index of a local index.
+ */
+ GlobalLookupIndexSet(const ParallelIndexSet& indexset);
+
+ /**
+ * @brief Destructor.
+ */
+ ~GlobalLookupIndexSet();
+
+ /**
+ * @brief Find the index pair with a specific global id.
+ *
+ * This starts a binary search for the entry and therefor has complexity
+ * N log(N). This method is forwarded to the underlying index set.
+ * @param global The globally unique id of the pair.
+ * @return The pair of indices for the id.
+ * @exception RangeError Thrown if the global id is not known.
+ */
+ inline const IndexPair&
+ operator[](const GlobalIndex& global) const;
+
+ /**
+ * @brief Get the index pair corresponding to a local index.
+ */
+ inline const IndexPair*
+ pair(const std::size_t& local) const;
+
+ /**
+ * @brief Get an iterator over the indices positioned at the first index.
+ * @return Iterator over the local indices.
+ */
+ inline const_iterator begin() const;
+
+ /**
+ * @brief Get an iterator over the indices positioned after the last index.
+ * @return Iterator over the local indices.
+ */
+ inline const_iterator end() const;
+
+ /**
+ * @brief Get the internal sequence number.
+ *
+ * Is initially 0 is incremented for each resize.
+ * @return The sequence number.
+ */
+ inline int seqNo() const;
+
+ /**
+ * @brief Get the total number (public and nonpublic) indices.
+ * @return The total number (public and nonpublic) indices.
+ */
+ inline size_t size() const;
+ private:
+ /**
+ * @brief The index set we lookup in.
+ */
+ const ParallelIndexSet& indexSet_;
+
+ /**
+ * @brief The number of indices.
+ */
+ std::size_t size_;
+
+ /**
+ * @brief Array with the positions of the corresponding index pair of the index set.
+ */
+ std::vector<const IndexPair*> indices_;
+
+ };
+
+
+ template<typename T>
+ struct LocalIndexComparator
+ {
+ static bool compare(const T& t1, const T& t2){
+ DUNE_UNUSED_PARAMETER(t1);
+ DUNE_UNUSED_PARAMETER(t2);
+ return false;
+ }
+ };
+
+ template<class TG, class TL>
+ struct IndexSetSortFunctor
+ {
+ bool operator()(const IndexPair<TG,TL>& i1, const IndexPair<TG,TL>& i2)
+ {
+ return i1.global()<i2.global() || (i1.global()==i2.global() &&
+ LocalIndexComparator<TL>::compare(i1.local(),
+ i2.local()));
+ }
+ };
+
+
+
+ template<class TG, class TL>
+ inline std::ostream& operator<<(std::ostream& os, const IndexPair<TG,TL>& pair)
+ {
+ os<<"{global="<<pair.global_<<", local="<<pair.local_<<"}";
+ return os;
+ }
+
+ template<class TG, class TL, int N>
+ inline std::ostream& operator<<(std::ostream& os, const ParallelIndexSet<TG,TL,N>& indexSet)
+ {
+ typedef typename ParallelIndexSet<TG,TL,N>::const_iterator Iterator;
+ Iterator end = indexSet.end();
+ os<<"{";
+ for(Iterator index = indexSet.begin(); index != end; ++index)
+ os<<*index<<" ";
+ os<<"}";
+ return os;
+
+ }
+
+ template<class TG, class TL>
+ inline bool operator==(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
+ {
+ return a.global_==b.global_;
+ }
+
+ template<class TG, class TL>
+ inline bool operator!=(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
+ {
+ return a.global_!=b.global_;
+ }
+
+ template<class TG, class TL>
+ inline bool operator<(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
+ {
+ return a.global_<b.global_;
+ }
+
+ template<class TG, class TL>
+ inline bool operator>(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
+ {
+ return a.global_>b.global_;
+ }
+
+ template<class TG, class TL>
+ inline bool operator<=(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
+ {
+ return a.global_<=b.global_;
+ }
+
+ template<class TG, class TL>
+ inline bool operator >=(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
+ {
+ return a.global_>=b.global_;
+ }
+
+ template<class TG, class TL>
+ inline bool operator==(const IndexPair<TG,TL>& a, const TG& b)
+ {
+ return a.global_==b;
+ }
+
+ template<class TG, class TL>
+ inline bool operator!=(const IndexPair<TG,TL>& a, const TG& b)
+ {
+ return a.global_!=b;
+ }
+
+ template<class TG, class TL>
+ inline bool operator<(const IndexPair<TG,TL>& a, const TG& b)
+ {
+ return a.global_<b;
+ }
+
+ template<class TG, class TL>
+ inline bool operator>(const IndexPair<TG,TL>& a, const TG& b)
+ {
+ return a.global_>b;
+ }
+
+ template<class TG, class TL>
+ inline bool operator<=(const IndexPair<TG,TL>& a, const TG& b)
+ {
+ return a.global_<=b;
+ }
+
+ template<class TG, class TL>
+ inline bool operator >=(const IndexPair<TG,TL>& a, const TG& b)
+ {
+ return a.global_>=b;
+ }
+
+#ifndef DOXYGEN
+
+ template<class TG, class TL>
+ IndexPair<TG,TL>::IndexPair(const TG& global, const TL& local)
+ : global_(global), local_(local){}
+
+ template<class TG, class TL>
+ IndexPair<TG,TL>::IndexPair(const TG& global)
+ : global_(global), local_(){}
+
+ template<class TG, class TL>
+ IndexPair<TG,TL>::IndexPair()
+ : global_(), local_(){}
+
+ template<class TG, class TL>
+ inline const TG& IndexPair<TG,TL>::global() const {
+ return global_;
+ }
+
+ template<class TG, class TL>
+ inline TL& IndexPair<TG,TL>::local() {
+ return local_;
+ }
+
+ template<class TG, class TL>
+ inline const TL& IndexPair<TG,TL>::local() const {
+ return local_;
+ }
+
+ template<class TG, class TL>
+ inline void IndexPair<TG,TL>::setLocal(int local){
+ local_=local;
+ }
+
+ template<class TG, class TL, int N>
+ ParallelIndexSet<TG,TL,N>::ParallelIndexSet()
+ : state_(GROUND), seqNo_(0)
+ {}
+
+ template<class TG, class TL, int N>
+ void ParallelIndexSet<TG,TL,N>::beginResize() throw(InvalidIndexSetState)
+ {
+
+ // Checks in unproductive code
+#ifndef NDEBUG
+ if(state_!=GROUND)
+ DUNE_THROW(InvalidIndexSetState,
+ "IndexSet has to be in GROUND state, when "
+ << "beginResize() is called!");
+#endif
+
+ state_ = RESIZE;
+ deletedEntries_ = false;
+ }
+
+ template<class TG, class TL, int N>
+ inline void ParallelIndexSet<TG,TL,N>::add(const GlobalIndex& global)
+ throw(InvalidIndexSetState)
+ {
+ // Checks in unproductive code
+#ifndef NDEBUG
+ if(state_ != RESIZE)
+ DUNE_THROW(InvalidIndexSetState, "Indices can only be added "
+ <<"while in RESIZE state!");
+#endif
+ newIndices_.push_back(IndexPair(global));
+ }
+
+ template<class TG, class TL, int N>
+ inline void ParallelIndexSet<TG,TL,N>::add(const TG& global, const TL& local)
+ throw(InvalidIndexSetState)
+ {
+ // Checks in unproductive code
+#ifndef NDEBUG
+ if(state_ != RESIZE)
+ DUNE_THROW(InvalidIndexSetState, "Indices can only be added "
+ <<"while in RESIZE state!");
+#endif
+ newIndices_.push_back(IndexPair(global,local));
+ }
+
+ template<class TG, class TL, int N>
+ inline void ParallelIndexSet<TG,TL,N>::markAsDeleted(const iterator& global)
+ throw(InvalidIndexSetState){
+ // Checks in unproductive code
+#ifndef NDEBUG
+ if(state_ != RESIZE)
+ DUNE_THROW(InvalidIndexSetState, "Indices can only be removed "
+ <<"while in RESIZE state!");
+#endif
+ deletedEntries_ = true;
+
+ global.markAsDeleted();
+ }
+
+ template<class TG, class TL, int N>
+ void ParallelIndexSet<TG,TL,N>::endResize() throw(InvalidIndexSetState){
+ // Checks in unproductive code
+#ifndef NDEBUG
+ if(state_ != RESIZE)
+ DUNE_THROW(InvalidIndexSetState, "endResize called while not "
+ <<"in RESIZE state!");
+#endif
+
+ std::sort(newIndices_.begin(), newIndices_.end(), IndexSetSortFunctor<TG,TL>());
+ merge();
+ seqNo_++;
+ state_ = GROUND;
+ }
+
+
+ template<class TG, class TL, int N>
+ inline void ParallelIndexSet<TG,TL,N>::merge(){
+ if(localIndices_.size()==0)
+ {
+ localIndices_=newIndices_;
+ newIndices_.clear();
+ }
+ else if(newIndices_.size()>0 || deletedEntries_)
+ {
+ ArrayList<IndexPair,N> tempPairs;
+ typedef typename ArrayList<IndexPair,N>::iterator iterator;
+ typedef typename ArrayList<IndexPair,N>::const_iterator const_iterator;
+
+ iterator old=localIndices_.begin();
+ iterator added=newIndices_.begin();
+ const const_iterator endold=localIndices_.end();
+ const const_iterator endadded=newIndices_.end();
+
+ while(old != endold && added!= endadded)
+ {
+ if(old->local().state()==DELETED) {
+ old.eraseToHere();
+ }
+ else
+ {
+ if(old->global() < added->global() ||
+ (old->global() == added->global()
+ && LocalIndexComparator<TL>::compare(old->local(),added->local())))
+ {
+ tempPairs.push_back(*old);
+ old.eraseToHere();
+ continue;
+ }else
+ {
+ tempPairs.push_back(*added);
+ added.eraseToHere();
+ }
+ }
+ }
+
+ while(old != endold)
+ {
+ if(old->local().state()!=DELETED) {
+ tempPairs.push_back(*old);
+ }
+ old.eraseToHere();
+ }
+
+ while(added!= endadded)
+ {
+ tempPairs.push_back(*added);
+ added.eraseToHere();
+ }
+ localIndices_ = tempPairs;
+ }
+ }
+
+
+ template<class TG, class TL, int N>
+ inline const IndexPair<TG,TL>&
+ ParallelIndexSet<TG,TL,N>::at(const TG& global) const
+ {
+ // perform a binary search
+ int low=0, high=localIndices_.size()-1, probe=-1;
+
+ while(low<high)
+ {
+ probe = (high + low) / 2;
+ if(global <= localIndices_[probe].global())
+ high = probe;
+ else
+ low = probe+1;
+ }
+
+ if(probe==-1)
+ DUNE_THROW(RangeError, "No entries!");
+
+ if( localIndices_[low].global() != global)
+ DUNE_THROW(RangeError, "Could not find entry of "<<global);
+ else
+ return localIndices_[low];
+ }
+
+ template<class TG, class TL, int N>
+ inline const IndexPair<TG,TL>&
+ ParallelIndexSet<TG,TL,N>::operator[](const TG& global) const
+ {
+ // perform a binary search
+ int low=0, high=localIndices_.size()-1, probe=-1;
+
+ while(low<high)
+ {
+ probe = (high + low) / 2;
+ if(global <= localIndices_[probe].global())
+ high = probe;
+ else
+ low = probe+1;
+ }
+
+ return localIndices_[low];
+ }
+ template<class TG, class TL, int N>
+ inline IndexPair<TG,TL>& ParallelIndexSet<TG,TL,N>::at(const TG& global)
+ {
+ // perform a binary search
+ int low=0, high=localIndices_.size()-1, probe=-1;
+
+ while(low<high)
+ {
+ probe = (high + low) / 2;
+ if(localIndices_[probe].global() >= global)
+ high = probe;
+ else
+ low = probe+1;
+ }
+
+ if(probe==-1)
+ DUNE_THROW(RangeError, "No entries!");
+
+ if( localIndices_[low].global() != global)
+ DUNE_THROW(RangeError, "Could not find entry of "<<global);
+ else
+ return localIndices_[low];
+ }
+
+ template<class TG, class TL, int N>
+ inline IndexPair<TG,TL>& ParallelIndexSet<TG,TL,N>::operator[](const TG& global)
+ {
+ // perform a binary search
+ int low=0, high=localIndices_.size()-1, probe=-1;
+
+ while(low<high)
+ {
+ probe = (high + low) / 2;
+ if(localIndices_[probe].global() >= global)
+ high = probe;
+ else
+ low = probe+1;
+ }
+
+ return localIndices_[low];
+ }
+ template<class TG, class TL, int N>
+ inline typename ParallelIndexSet<TG,TL,N>::iterator
+ ParallelIndexSet<TG,TL,N>::begin()
+ {
+ return iterator(*this, localIndices_.begin());
+ }
+
+
+ template<class TG, class TL, int N>
+ inline typename ParallelIndexSet<TG,TL,N>::iterator
+ ParallelIndexSet<TG,TL,N>::end()
+ {
+ return iterator(*this,localIndices_.end());
+ }
+
+ template<class TG, class TL, int N>
+ inline typename ParallelIndexSet<TG,TL,N>::const_iterator
+ ParallelIndexSet<TG,TL,N>::begin() const
+ {
+ return localIndices_.begin();
+ }
+
+
+ template<class TG, class TL, int N>
+ inline typename ParallelIndexSet<TG,TL,N>::const_iterator
+ ParallelIndexSet<TG,TL,N>::end() const
+ {
+ return localIndices_.end();
+ }
+
+ template<class TG, class TL, int N>
+ void ParallelIndexSet<TG,TL,N>::renumberLocal(){
+#ifndef NDEBUG
+ if(state_==RESIZE)
+ DUNE_THROW(InvalidIndexSetState, "IndexSet has to be in "
+ <<"GROUND state for renumberLocal()");
+#endif
+
+ typedef typename ArrayList<IndexPair,N>::iterator iterator;
+ const const_iterator end_ = end();
+ uint32_t index=0;
+
+ for(iterator pair=begin(); pair!=end_; index++, ++pair)
+ pair->local()=index;
+ }
+
+ template<class TG, class TL, int N>
+ inline int ParallelIndexSet<TG,TL,N>::seqNo() const
+ {
+ return seqNo_;
+ }
+
+ template<class TG, class TL, int N>
+ inline size_t ParallelIndexSet<TG,TL,N>::size() const
+ {
+ return localIndices_.size();
+ }
+
+ template<class I>
+ GlobalLookupIndexSet<I>::GlobalLookupIndexSet(const I& indexset,
+ std::size_t size)
+ : indexSet_(indexset), size_(size),
+ indices_(size_, static_cast<const IndexPair*>(0))
+ {
+ const_iterator end_ = indexSet_.end();
+
+ for(const_iterator pair = indexSet_.begin(); pair!=end_; ++pair) {
+ assert(pair->local()<size_);
+ indices_[pair->local()] = &(*pair);
+ }
+ }
+
+ template<class I>
+ GlobalLookupIndexSet<I>::GlobalLookupIndexSet(const I& indexset)
+ : indexSet_(indexset), size_(0)
+ {
+ const_iterator end_ = indexSet_.end();
+ for(const_iterator pair = indexSet_.begin(); pair!=end_; ++pair)
+ size_=std::max(size_,static_cast<std::size_t>(pair->local()));
+
+ indices_.resize(++size_, 0);
+
+ for(const_iterator pair = indexSet_.begin(); pair!=end_; ++pair)
+ indices_[pair->local()] = &(*pair);
+ }
+
+ template<class I>
+ GlobalLookupIndexSet<I>::~GlobalLookupIndexSet()
+ {}
+
+ template<class I>
+ inline const IndexPair<typename I::GlobalIndex, typename I::LocalIndex>*
+ GlobalLookupIndexSet<I>::pair(const std::size_t& local) const
+ {
+ return indices_[local];
+ }
+
+ template<class I>
+ inline const IndexPair<typename I::GlobalIndex, typename I::LocalIndex>&
+ GlobalLookupIndexSet<I>::operator[](const GlobalIndex& global) const
+ {
+ return indexSet_[global];
+ }
+
+ template<class I>
+ typename I::const_iterator GlobalLookupIndexSet<I>::begin() const
+ {
+ return indexSet_.begin();
+ }
+
+ template<class I>
+ typename I::const_iterator GlobalLookupIndexSet<I>::end() const
+ {
+ return indexSet_.end();
+ }
+
+ template<class I>
+ inline size_t GlobalLookupIndexSet<I>::size() const
+ {
+ return size_;
+ }
+
+ template<class I>
+ inline int GlobalLookupIndexSet<I>::seqNo() const
+ {
+ return indexSet_.seqNo();
+ }
+
+ template<typename TG, typename TL, int N, typename TG1, typename TL1, int N1>
+ bool operator==(const ParallelIndexSet<TG,TL,N>& idxset,
+ const ParallelIndexSet<TG1,TL1,N1>& idxset1)
+ {
+ if(idxset.size()!=idxset1.size())
+ return false;
+ typedef typename ParallelIndexSet<TG,TL,N>::const_iterator Iter;
+ typedef typename ParallelIndexSet<TG1,TL1,N1>::const_iterator Iter1;
+ Iter iter=idxset.begin();
+ for(Iter1 iter1=idxset1.begin(); iter1 != idxset1.end(); ++iter, ++iter1) {
+ if(iter1->global()!=iter->global())
+ return false;
+ typedef typename ParallelIndexSet<TG,TL,N>::LocalIndex PI;
+ const PI& pi=iter->local(), pi1=iter1->local();
+
+ if(pi!=pi1)
+ return false;
+ }
+ return true;
+ }
+
+ template<typename TG, typename TL, int N, typename TG1, typename TL1, int N1>
+ bool operator!=(const ParallelIndexSet<TG,TL,N>& idxset,
+ const ParallelIndexSet<TG1,TL1,N1>& idxset1)
+ {
+ return !(idxset==idxset1);
+ }
+
+
+#endif // DOXYGEN
+
+}
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+#ifndef DUNE_INDICESSYNCER_HH
+#define DUNE_INDICESSYNCER_HH
+
+#include "indexset.hh"
+#include "remoteindices.hh"
+#include <dune/common/stdstreams.hh>
+#include <dune/common/tuples.hh>
+#include <dune/common/sllist.hh>
+#include <dune/common/unused.hh>
+#include <cassert>
+#include <cmath>
+#include <limits>
+#include <algorithm>
+#include <functional>
+#include <map>
+
+#if HAVE_MPI
+namespace Dune
+{
+ /** @addtogroup Common_Parallel
+ *
+ * @{
+ */
+ /**
+ * @file
+ * @brief Class for adding missing indices of a distributed index set in a local
+ * communication.
+ * @author Markus Blatt
+ */
+
+ /**
+ * @brief Class for recomputing missing indices of a distributed index set.
+ *
+ * Missing local and remote indices will be added.
+ */
+ template<typename T>
+ class IndicesSyncer
+ {
+ public:
+
+ /** @brief The type of the index set. */
+ typedef T ParallelIndexSet;
+
+ /** @brief The type of the index pair */
+ typedef typename ParallelIndexSet::IndexPair IndexPair;
+
+ /** @brief Type of the global index used in the index set. */
+ typedef typename ParallelIndexSet::GlobalIndex GlobalIndex;
+
+ /** @brief Type of the attribute used in the index set. */
+ typedef typename ParallelIndexSet::LocalIndex::Attribute Attribute;
+
+ /**
+ * @brief Type of the remote indices.
+ */
+ typedef Dune::RemoteIndices<ParallelIndexSet> RemoteIndices;
+
+ /**
+ * @brief Constructor.
+ *
+ * The source as well as the target index set of the remote
+ * indices have to be the same as the provided index set.
+ * @param indexSet The index set with the information
+ * of the locally present indices.
+ * @param remoteIndices The remoteIndices.
+ */
+ IndicesSyncer(ParallelIndexSet& indexSet,
+ RemoteIndices& remoteIndices);
+
+ /**
+ * @brief Sync the index set.
+ *
+ * Computes the missing indices in the local and the remote index list and adds them.
+ * No global communication is necessary!
+ * All indices added to the index will become the local index
+ * std::numeric_limits<size_t>::max()
+ *
+ */
+ void sync();
+
+ /**
+ * @brief Synce the index set and assign local numbers to new indices
+ *
+ * Computes the missing indices in the local and the remote index list and adds them.
+ * No global communication is necessary!
+ * @param numberer Functor providing the local indices for the added global indices.
+ * has to provide a function size_t operator()(const TG& global) that provides the
+ * local index to a global one. It will be called for ascending global indices.
+ *
+ */
+ template<typename T1>
+ void sync(T1& numberer);
+
+ private:
+
+ /** @brief The set of locally present indices.*/
+ ParallelIndexSet& indexSet_;
+
+ /** @brief The remote indices. */
+ RemoteIndices& remoteIndices_;
+
+ /** @brief The send buffers for the neighbour processes. */
+ char** sendBuffers_;
+
+ /** @brief The receive buffer. */
+ char* receiveBuffer_;
+
+ /** @brief The size of the send buffers. */
+ std::size_t* sendBufferSizes_;
+
+ /** @brief The size of the receive buffer in bytes. */
+ int receiveBufferSize_; // int because of MPI
+
+ /**
+ * @brief Information about the messages to send to a neighbouring process.
+ */
+ struct MessageInformation
+ {
+ MessageInformation()
+ : publish(), pairs()
+ {}
+ /** @brief The number of indices we publish for the other process. */
+ int publish;
+ /**
+ * @brief The number of pairs (attribute and process number)
+ * we publish to the neighbour process.
+ */
+ int pairs;
+ };
+
+ /**
+ * @brief Default numberer for sync().
+ */
+ class DefaultNumberer
+ {
+ public:
+ /**
+ * @brief Provide the lcoal index, always
+ * std::numeric_limits<size_t>::max()
+ * @param global The global index (ignored).
+ */
+ std::size_t operator()(const GlobalIndex& global)
+ {
+ DUNE_UNUSED_PARAMETER(global);
+ return std::numeric_limits<size_t>::max();
+ }
+ };
+
+ /** @brief The mpi datatype for the MessageInformation */
+ MPI_Datatype datatype_;
+
+ /** @brief Our rank. */
+ int rank_;
+
+ /**
+ * @brief List type for temporarily storing the global indices of the
+ * remote indices.
+ */
+ typedef SLList<std::pair<GlobalIndex,Attribute>, typename RemoteIndices::Allocator> GlobalIndexList;
+
+ /** @brief The modifying iterator for the global index list. */
+ typedef typename GlobalIndexList::ModifyIterator GlobalIndexModifier;
+
+ /**
+ * @brief The type of the iterator of GlobalIndexList
+ */
+ typedef typename SLList<GlobalIndex, typename RemoteIndices::Allocator>::iterator
+ GlobalIndexIterator;
+
+ /** @brief Type of the map of ranks onto GlobalIndexLists. */
+ typedef std::map<int, GlobalIndexList> GlobalIndicesMap;
+
+ /**
+ * @brief Map of global index lists onto process ranks.
+ *
+ * As the pointers in the remote index lists become invalid due to
+ * resorting the index set entries one has store the corresponding
+ * global index for each remote index. Thus the pointers can be adjusted
+ * properly as a last step.
+ */
+ GlobalIndicesMap globalMap_;
+
+ /**
+ * @brief The type of the single linked list of bools.
+ */
+ typedef SLList<bool, typename RemoteIndices::Allocator> BoolList;
+
+ /**
+ * @brief The mutable iterator of the single linked bool list.
+ */
+ typedef typename BoolList::iterator BoolIterator;
+
+ /** @brief The type of the modifying iterator for the list of bools. */
+ typedef typename BoolList::ModifyIterator BoolListModifier;
+
+ /** @brief The type of the map of bool lists. */
+ typedef std::map<int,BoolList> BoolMap;
+
+ /**
+ * @brief Map of lists of bool indicating whether the remote index was present before
+ * call of sync.
+ */
+ BoolMap oldMap_;
+
+ /** @brief Information about the messages we send. */
+ std::map<int,MessageInformation> infoSend_;
+
+ /** @brief The type of the remote index list. */
+ typedef typename RemoteIndices::RemoteIndexList RemoteIndexList;
+
+ /** @brief The tyoe of the modifying iterator of the remote index list. */
+ typedef typename RemoteIndexList::ModifyIterator RemoteIndexModifier;
+
+ /** @brief The type of the remote inde. */
+ typedef Dune::RemoteIndex<GlobalIndex,Attribute> RemoteIndex;
+
+ /** @brief The iterator of the remote index list. */
+ typedef typename RemoteIndexList::iterator RemoteIndexIterator;
+
+ /** @brief The const iterator of the remote index list. */
+ typedef typename RemoteIndexList::const_iterator ConstRemoteIndexIterator;
+
+ /** @brief Type of the tuple of iterators needed for the adding of indices. */
+ typedef Dune::tuple<RemoteIndexModifier,GlobalIndexModifier,BoolListModifier,
+ const ConstRemoteIndexIterator> IteratorTuple;
+
+ /**
+ * @brief A tuple of iterators.
+ *
+ * Insertion into a single linked list is only possible at the position after the one of the iterator.
+ * Therefore for each linked list two iterators are needed: One position before the actual entry
+ * (for insertion) and one positioned at the actual position (for searching).
+ */
+ class Iterators
+ {
+ friend class IndicesSyncer<T>;
+ public:
+ /**
+ * @brief Constructor.
+ *
+ * Initializes all iterator to first entry and the one before the first entry, respectively.
+ * @param remoteIndices The list of the remote indices.
+ * @param globalIndices The list of the coresponding global indices. This is needed because the
+ * the pointers to the local index will become invalid due to the merging of the index sets.
+ * @param booleans Whether the remote index was there before the sync process started.
+ */
+ Iterators(RemoteIndexList& remoteIndices, GlobalIndexList& globalIndices,
+ BoolList& booleans);
+
+ /**
+ * @brief Default constructor.
+ */
+ Iterators();
+
+ /**
+ * @brief Increment all iteraors.
+ */
+ Iterators& operator++();
+
+ /**
+ * @brief Insert a new remote index to the underlying remote index list.
+ * @param index The remote index.
+ * @param global The global index corresponding to the remote index.
+ */
+ void insert(const RemoteIndex& index,
+ const std::pair<GlobalIndex,Attribute>& global);
+
+ /**
+ * @brief Get the remote index at current position.
+ * @return The current remote index.
+ */
+ RemoteIndex& remoteIndex() const;
+
+ /**
+ * @brief Get the global index of the remote index at current position.
+ * @return The current global index.
+ */
+ std::pair<GlobalIndex,Attribute>& globalIndexPair() const;
+
+ Attribute& attribute() const;
+
+ /**
+ * @brief Was this entry already in the remote index list before the sync process?
+ * @return True if the current index wasalready in the remote index list
+ * before the sync process.
+ */
+ bool isOld() const;
+
+ /**
+ * @brief Reset all the underlying iterators.
+ *
+ * Position them to first list entry and the entry before the first entry respectively.
+ * @param remoteIndices The list of the remote indices.
+ * @param globalIndices The list of the coresponding global indices. This is needed because the
+ * the pointers to the local index will become invalid due to the merging of the index sets.
+ * @param booleans Whether the remote index was there before the sync process started.
+ */
+ void reset(RemoteIndexList& remoteIndices, GlobalIndexList& globalIndices,
+ BoolList& booleans);
+
+ /**
+ * @brief Are we not at the end of the list?
+ * @return True if the iterators are not positioned at the end of the list
+ * and the tail of the list respectively.
+ */
+ bool isNotAtEnd() const;
+
+ /**
+ * @brief Are we at the end of the list?
+ * @return True if the iterators are positioned at the end of the list
+ * and the tail of the list respectively.
+ */
+ bool isAtEnd() const;
+
+ private:
+ /**
+ * @brief The iterator tuple.
+ *
+ * The tuple consists of one iterator over a single linked list of remote indices
+ * initially positioned before the first entry, one over a sll of global indices
+ * , one over a all of bool values both postioned at the same entry. The another three
+ * iterators of the same type positioned at the first entry. Last an iterator over the
+ * sll of remote indices positioned at the end.
+ */
+ IteratorTuple iterators_;
+ };
+
+ /** @brief Type of the map from ranks to iterator tuples. */
+ typedef std::map<int,Iterators> IteratorsMap;
+
+ /**
+ * @brief The iterator tuples mapped on the neighbours.
+ *
+ * The key of the map is the rank of the neighbour.
+ * The first entry in the tuple is an iterator over the remote indices
+ * initially positioned before the first entry. The second entry is an
+ * iterator over the corresponding global indices also initially positioned
+ * before the first entry. The third entry an iterator over remote indices
+ * initially positioned at the beginning. The last entry is the iterator over
+ * the remote indices positioned at the end.
+ */
+ IteratorsMap iteratorsMap_;
+
+ /** @brief Calculates the message sizes to send. */
+ void calculateMessageSizes();
+
+ /**
+ * @brief Pack and send the message for another process.
+ * @param destination The rank of the process we send to.
+ * @param buffer The allocated buffer to use.
+ * @param bufferSize The size of the buffer.
+ * @param req The MPI_Request to setup the nonblocking send.
+ */
+ void packAndSend(int destination, char* buffer, std::size_t bufferSize, MPI_Request& req);
+
+ /**
+ * @brief Recv and unpack the message from another process and add the indices.
+ * @param numberer Functor providing local indices for added global indices.
+ */
+ template<typename T1>
+ void recvAndUnpack(T1& numberer);
+
+ /**
+ * @brief Register the MPI datatype for the MessageInformation.
+ */
+ void registerMessageDatatype();
+
+ /**
+ * @brief Insert an entry into the remote index list if not yet present.
+ */
+ void insertIntoRemoteIndexList(int process,
+ const std::pair<GlobalIndex,Attribute>& global,
+ char attribute);
+
+ /**
+ * @brief Reset the iterator tuples of all neighbouring processes.
+ */
+ void resetIteratorsMap();
+
+ /**
+ * @brief Check whether the iterator tuples of all neighbouring processes
+ * are reset.
+ */
+ bool checkReset();
+
+ /**
+ * @brief Check whether the iterator tuple is reset.
+ *
+ * @param iterators The iterator tuple to check.
+ * @param rlist The SLList of the remote indices.
+ * @param gList The SLList of the global indices.
+ * @param bList The SLList of the bool values.
+ */
+ bool checkReset(const Iterators& iterators, RemoteIndexList& rlist, GlobalIndexList& gList,
+ BoolList& bList);
+ };
+
+ template<typename TG, typename TA>
+ bool operator<(const IndexPair<TG,ParallelLocalIndex<TA> >& i1,
+ const std::pair<TG,TA>& i2)
+ {
+ return i1.global() < i2.first ||
+ (i1.global() == i2.first && i1.local().attribute()<i2.second);
+ }
+
+ template<typename TG, typename TA>
+ bool operator<(const std::pair<TG,TA>& i1,
+ const IndexPair<TG,ParallelLocalIndex<TA> >& i2)
+ {
+ return i1.first < i2.global() ||
+ (i1.first == i2.global() && i1.second<i2.local().attribute());
+ }
+
+ template<typename TG, typename TA>
+ bool operator==(const IndexPair<TG,ParallelLocalIndex<TA> >& i1,
+ const std::pair<TG,TA>& i2)
+ {
+ return (i1.global() == i2.first && i1.local().attribute()==i2.second);
+ }
+
+ template<typename TG, typename TA>
+ bool operator!=(const IndexPair<TG,ParallelLocalIndex<TA> >& i1,
+ const std::pair<TG,TA>& i2)
+ {
+ return (i1.global() != i2.first || i1.local().attribute()!=i2.second);
+ }
+
+ template<typename TG, typename TA>
+ bool operator==(const std::pair<TG,TA>& i2,
+ const IndexPair<TG,ParallelLocalIndex<TA> >& i1)
+ {
+ return (i1.global() == i2.first && i1.local().attribute()==i2.second);
+ }
+
+ template<typename TG, typename TA>
+ bool operator!=(const std::pair<TG,TA>& i2,
+ const IndexPair<TG,ParallelLocalIndex<TA> >& i1)
+ {
+ return (i1.global() != i2.first || i1.local().attribute()!=i2.second);
+ }
+
+ /**
+ * @brief Stores the corresponding global indices of the remote index information.
+ *
+ * Whenever a ParallelIndexSet is resized all RemoteIndices that use it will be invalided
+ * as the pointers to the index set are invalid after calling ParallelIndexSet::Resize()
+ * One can rebuild them by storing the global indices in a map with this function and later
+ * repairing the pointers by calling repairLocalIndexPointers.
+ *
+ * @warning The RemoteIndices class has to be build with the same index set for both the
+ * sending and receiving side
+ * @param globalMap Map to store the corresponding global indices in.
+ * @param remoteIndices The remote index information we need to store the corresponding global
+ * indices of.
+ * @param indexSet The index set that is for both the sending and receiving side of the remote
+ * index information.
+ */
+ template<typename T, typename A, typename A1>
+ void storeGlobalIndicesOfRemoteIndices(std::map<int,SLList<std::pair<typename T::GlobalIndex, typename T::LocalIndex::Attribute>,A> >& globalMap,
+ const RemoteIndices<T,A1>& remoteIndices,
+ const T& indexSet)
+ {
+ typedef typename RemoteIndices<T,A1>::const_iterator RemoteIterator;
+
+ for(RemoteIterator remote = remoteIndices.begin(), end =remoteIndices.end(); remote != end; ++remote) {
+ typedef typename RemoteIndices<T,A1>::RemoteIndexList RemoteIndexList;
+ typedef typename RemoteIndexList::const_iterator RemoteIndexIterator;
+ typedef SLList<std::pair<typename T::GlobalIndex, typename T::LocalIndex::Attribute>,A> GlobalIndexList;
+ GlobalIndexList& global = globalMap[remote->first];
+ RemoteIndexList& rList = *(remote->second.first);
+
+ for(RemoteIndexIterator index = rList.begin(), riEnd = rList.end();
+ index != riEnd; ++index) {
+ global.push_back(std::make_pair(index->localIndexPair().global(),
+ index->localIndexPair().local().attribute()));
+ }
+ }
+ }
+
+ /**
+ * @brief Repair the pointers to the local indices in the remote indices.
+ *
+ * @param globalMap The map of the process number to the list of global indices
+ * corresponding to the remote index list of the process.
+ * @param remoteIndices The known remote indices.
+ * @param indexSet The set of local indices of the current process.
+ */
+ template<typename T, typename A, typename A1>
+ inline void repairLocalIndexPointers(std::map<int,
+ SLList<std::pair<typename T::GlobalIndex,
+ typename T::LocalIndex::Attribute>,A> >& globalMap,
+ RemoteIndices<T,A1>& remoteIndices,
+ const T& indexSet)
+ {
+ typedef typename RemoteIndices<T,A1>::RemoteIndexMap::iterator RemoteIterator;
+ typedef typename RemoteIndices<T,A1>::RemoteIndexList::iterator RemoteIndexIterator;
+ typedef typename T::GlobalIndex GlobalIndex;
+ typedef typename T::LocalIndex::Attribute Attribute;
+ typedef std::pair<GlobalIndex,Attribute> GlobalIndexPair;
+ typedef SLList<GlobalIndexPair,A> GlobalIndexPairList;
+ typedef typename GlobalIndexPairList::iterator GlobalIndexIterator;
+
+ assert(globalMap.size()==static_cast<std::size_t>(remoteIndices.neighbours()));
+ // Repair pointers to index set in remote indices.
+ typename std::map<int,GlobalIndexPairList>::iterator global = globalMap.begin();
+ RemoteIterator end = remoteIndices.remoteIndices_.end();
+
+ for(RemoteIterator remote = remoteIndices.remoteIndices_.begin(); remote != end; ++remote, ++global) {
+ typedef typename T::const_iterator IndexIterator;
+
+ assert(remote->first==global->first);
+ assert(remote->second.first->size() == global->second.size());
+
+ RemoteIndexIterator riEnd = remote->second.first->end();
+ RemoteIndexIterator rIndex = remote->second.first->begin();
+ GlobalIndexIterator gIndex = global->second.begin();
+ IndexIterator index = indexSet.begin();
+
+ assert(rIndex==riEnd || gIndex != global->second.end());
+ while(rIndex != riEnd) {
+ // Search for the index in the set.
+ assert(gIndex != global->second.end());
+
+ while(!(index->global() == gIndex->first
+ && index->local().attribute() == gIndex->second)) {
+ ++index;
+ // this is only needed for ALU, where there may exist
+ // more entries with the same global index in the remote index set
+ // than in the index set
+ if (index->global() > gIndex->first) {
+ index=indexSet.begin();
+ }
+ }
+
+ assert(index != indexSet.end() && *index == *gIndex);
+
+ rIndex->localIndex_ = &(*index);
+ ++index;
+ ++rIndex;
+ ++gIndex;
+ }
+ }
+ remoteIndices.sourceSeqNo_ = remoteIndices.source_->seqNo();
+ remoteIndices.destSeqNo_ = remoteIndices.target_->seqNo();
+ }
+
+ template<typename T>
+ IndicesSyncer<T>::IndicesSyncer(ParallelIndexSet& indexSet,
+ RemoteIndices& remoteIndices)
+ : indexSet_(indexSet), remoteIndices_(remoteIndices)
+ {
+ // index sets must match.
+ assert(remoteIndices.source_ == remoteIndices.target_);
+ assert(remoteIndices.source_ == &indexSet);
+ MPI_Comm_rank(remoteIndices_.communicator(), &rank_);
+ }
+
+ template<typename T>
+ IndicesSyncer<T>::Iterators::Iterators(RemoteIndexList& remoteIndices,
+ GlobalIndexList& globalIndices,
+ BoolList& booleans)
+ : iterators_(remoteIndices.beginModify(), globalIndices.beginModify(),
+ booleans.beginModify(), remoteIndices.end())
+ { }
+
+ template<typename T>
+ IndicesSyncer<T>::Iterators::Iterators()
+ : iterators_()
+ {}
+
+ template<typename T>
+ inline typename IndicesSyncer<T>::Iterators& IndicesSyncer<T>::Iterators::operator++()
+ {
+ ++(get<0>(iterators_));
+ ++(get<1>(iterators_));
+ ++(get<2>(iterators_));
+ return *this;
+ }
+
+ template<typename T>
+ inline void IndicesSyncer<T>::Iterators::insert(const RemoteIndex & index,
+ const std::pair<GlobalIndex,Attribute>& global)
+ {
+ get<0>(iterators_).insert(index);
+ get<1>(iterators_).insert(global);
+ get<2>(iterators_).insert(false);
+ }
+
+ template<typename T>
+ inline typename IndicesSyncer<T>::RemoteIndex&
+ IndicesSyncer<T>::Iterators::remoteIndex() const
+ {
+ return *(get<0>(iterators_));
+ }
+
+ template<typename T>
+ inline std::pair<typename IndicesSyncer<T>::GlobalIndex,typename IndicesSyncer<T>::Attribute>&
+ IndicesSyncer<T>::Iterators::globalIndexPair() const
+ {
+ return *(get<1>(iterators_));
+ }
+
+ template<typename T>
+ inline bool IndicesSyncer<T>::Iterators::isOld() const
+ {
+ return *(get<2>(iterators_));
+ }
+
+ template<typename T>
+ inline void IndicesSyncer<T>::Iterators::reset(RemoteIndexList& remoteIndices,
+ GlobalIndexList& globalIndices,
+ BoolList& booleans)
+ {
+ get<0>(iterators_) = remoteIndices.beginModify();
+ get<1>(iterators_) = globalIndices.beginModify();
+ get<2>(iterators_) = booleans.beginModify();
+ }
+
+ template<typename T>
+ inline bool IndicesSyncer<T>::Iterators::isNotAtEnd() const
+ {
+ return get<0>(iterators_)!=get<3>(iterators_);
+ }
+
+ template<typename T>
+ inline bool IndicesSyncer<T>::Iterators::isAtEnd() const
+ {
+ return get<0>(iterators_)==get<3>(iterators_);
+ }
+
+ template<typename T>
+ void IndicesSyncer<T>::registerMessageDatatype()
+ {
+ MPI_Datatype type[2] = {MPI_INT, MPI_INT};
+ int blocklength[2] = {1,1};
+ MPI_Aint displacement[2];
+ MPI_Aint base;
+
+ // Compute displacement
+ MessageInformation message;
+
+ MPI_Address( &(message.publish), displacement);
+ MPI_Address( &(message.pairs), displacement+1);
+
+ // Make the displacement relative
+ MPI_Address(&message, &base);
+ displacement[0] -= base;
+ displacement[1] -= base;
+
+ MPI_Type_struct( 2, blocklength, displacement, type, &datatype_);
+ MPI_Type_commit(&datatype_);
+ }
+
+ template<typename T>
+ void IndicesSyncer<T>::calculateMessageSizes()
+ {
+ typedef typename ParallelIndexSet::const_iterator IndexIterator;
+ typedef CollectiveIterator<T,typename RemoteIndices::Allocator> CollectiveIterator;
+
+ IndexIterator iEnd = indexSet_.end();
+ CollectiveIterator collIter = remoteIndices_.template iterator<true>();
+
+ for(IndexIterator index = indexSet_.begin(); index != iEnd; ++index) {
+ collIter.advance(index->global(), index->local().attribute());
+ if(collIter.empty())
+ break;
+ int knownRemote=0;
+
+ typedef typename CollectiveIterator::iterator ValidIterator;
+ ValidIterator end = collIter.end();
+
+ // Count the remote indices we know.
+ for(ValidIterator valid = collIter.begin(); valid != end; ++valid) {
+ ++knownRemote;
+ }
+
+ if(knownRemote>0) {
+ Dune::dverb<<rank_<<": publishing "<<knownRemote<<" for index "<<index->global()<< " for processes ";
+
+ // Update MessageInformation
+ for(ValidIterator valid = collIter.begin(); valid != end; ++valid) {
+ ++(infoSend_[valid.process()].publish);
+ (infoSend_[valid.process()].pairs) += knownRemote;
+ Dune::dverb<<valid.process()<<" ";
+ Dune::dverb<<"(publish="<<infoSend_[valid.process()].publish<<", pairs="<<infoSend_[valid.process()].pairs
+ <<") ";
+ }
+ Dune::dverb<<std::endl;
+ }
+ }
+
+ typedef typename std::map<int,MessageInformation>::const_iterator
+ MessageIterator;
+
+ const MessageIterator end = infoSend_.end();
+
+ // registerMessageDatatype();
+
+ // Now determine the buffersizes needed for each neighbour using MPI_Pack_size
+ MessageInformation dummy;
+
+ MessageIterator messageIter= infoSend_.begin();
+
+ typedef typename RemoteIndices::RemoteIndexMap::const_iterator RemoteIterator;
+ const RemoteIterator rend = remoteIndices_.end();
+ int neighbour=0;
+
+ for(RemoteIterator remote = remoteIndices_.begin(); remote != rend; ++remote, ++neighbour) {
+ MessageInformation* message;
+ MessageInformation recv;
+
+ if(messageIter != end && messageIter->first==remote->first) {
+ // We want to send message information to that process
+ message = const_cast<MessageInformation*>(&(messageIter->second));
+ ++messageIter;
+ }else
+ // We do not want to send information but the other process might.
+ message = &dummy;
+
+ sendBufferSizes_[neighbour]=0;
+ int tsize;
+ // The number of indices published
+ MPI_Pack_size(1, MPI_INT,remoteIndices_.communicator(), &tsize);
+ sendBufferSizes_[neighbour] += tsize;
+
+ for(int i=0; i < message->publish; ++i) {
+ // The global index
+ MPI_Pack_size(1, MPITraits<GlobalIndex>::getType(), remoteIndices_.communicator(), &tsize);
+ sendBufferSizes_[neighbour] += tsize;
+ // The attribute in the local index
+ MPI_Pack_size(1, MPI_CHAR, remoteIndices_.communicator(), &tsize);
+ sendBufferSizes_[neighbour] += tsize;
+ // The number of corresponding remote indices
+ MPI_Pack_size(1, MPI_INT, remoteIndices_.communicator(), &tsize);
+ sendBufferSizes_[neighbour] += tsize;
+ }
+ for(int i=0; i < message->pairs; ++i) {
+ // The process of the remote index
+ MPI_Pack_size(1, MPI_INT, remoteIndices_.communicator(), &tsize);
+ sendBufferSizes_[neighbour] += tsize;
+ // The attribute of the remote index
+ MPI_Pack_size(1, MPI_CHAR, remoteIndices_.communicator(), &tsize);
+ sendBufferSizes_[neighbour] += tsize;
+ }
+
+ Dune::dverb<<rank_<<": Buffer (neighbour="<<remote->first<<") size is "<< sendBufferSizes_[neighbour]<<" for publish="<<message->publish<<" pairs="<<message->pairs<<std::endl;
+ }
+
+ }
+
+ template<typename T>
+ inline void IndicesSyncer<T>::sync()
+ {
+ DefaultNumberer numberer;
+ sync(numberer);
+ }
+
+ template<typename T>
+ template<typename T1>
+ void IndicesSyncer<T>::sync(T1& numberer)
+ {
+
+ // The pointers to the local indices in the remote indices
+ // will become invalid due to the resorting of the index set.
+ // Therefore store the corresponding global indices.
+ // Mark all indices as not added
+
+ typedef typename RemoteIndices::RemoteIndexMap::const_iterator
+ RemoteIterator;
+
+ const RemoteIterator end = remoteIndices_.end();
+
+ // Number of neighbours might change during the syncing.
+ // save the old neighbours
+ std::size_t noOldNeighbours = remoteIndices_.neighbours();
+ int* oldNeighbours = new int[noOldNeighbours];
+ sendBufferSizes_ = new std::size_t[noOldNeighbours];
+ std::size_t i=0;
+
+ for(RemoteIterator remote = remoteIndices_.begin(); remote != end; ++remote, ++i) {
+ typedef typename RemoteIndices::RemoteIndexList::const_iterator
+ RemoteIndexIterator;
+
+ oldNeighbours[i]=remote->first;
+
+ // Make sure we only have one remote index list.
+ assert(remote->second.first==remote->second.second);
+
+ RemoteIndexList& rList = *(remote->second.first);
+
+ // Store the corresponding global indices.
+ GlobalIndexList& global = globalMap_[remote->first];
+ BoolList& added = oldMap_[remote->first];
+ RemoteIndexIterator riEnd = rList.end();
+
+ for(RemoteIndexIterator index = rList.begin();
+ index != riEnd; ++index) {
+ global.push_back(std::make_pair(index->localIndexPair().global(),
+ index->localIndexPair().local().attribute()));
+ added.push_back(true);
+ }
+
+ Iterators iterators(rList, global, added);
+ iteratorsMap_.insert(std::make_pair(remote->first, iterators));
+ assert(checkReset(iteratorsMap_[remote->first], rList,global,added));
+ }
+
+ // Exchange indices with each neighbour
+ calculateMessageSizes();
+
+ // Allocate the buffers
+ receiveBufferSize_=1;
+ sendBuffers_ = new char*[noOldNeighbours];
+
+ for(std::size_t i=0; i<noOldNeighbours; ++i) {
+ sendBuffers_[i] = new char[sendBufferSizes_[i]];
+ receiveBufferSize_ = std::max(receiveBufferSize_, static_cast<int>(sendBufferSizes_[i]));
+ }
+
+ receiveBuffer_=new char[receiveBufferSize_];
+
+ indexSet_.beginResize();
+
+ Dune::dverb<<rank_<<": Neighbours: ";
+
+ for(i = 0; i<noOldNeighbours; ++i)
+ Dune::dverb<<oldNeighbours[i]<<" ";
+
+ Dune::dverb<<std::endl;
+
+ MPI_Request* requests = new MPI_Request[noOldNeighbours];
+ MPI_Status* statuses = new MPI_Status[noOldNeighbours];
+
+ // Pack Message data and start the sends
+ for(i = 0; i<noOldNeighbours; ++i)
+ packAndSend(oldNeighbours[i], sendBuffers_[i], sendBufferSizes_[i], requests[i]);
+
+ // Probe for incoming messages, receive and unpack them
+ for(i = 0; i<noOldNeighbours; ++i)
+ recvAndUnpack(numberer);
+ // }else{
+ // recvAndUnpack(oldNeighbours[i], numberer);
+ // packAndSend(oldNeighbours[i]);
+ // }
+ // }
+
+ delete[] receiveBuffer_;
+
+ // Wait for the completion of the sends
+ // Wait for completion of sends
+ if(MPI_SUCCESS!=MPI_Waitall(noOldNeighbours, requests, statuses)) {
+ std::cerr<<": MPI_Error occurred while sending message"<<std::endl;
+ for(i=0; i< noOldNeighbours; i++)
+ if(MPI_SUCCESS!=statuses[i].MPI_ERROR)
+ std::cerr<<"Destination "<<statuses[i].MPI_SOURCE<<" error code: "<<statuses[i].MPI_ERROR<<std::endl;
+ }
+
+ delete[] statuses;
+ delete[] requests;
+
+ for(std::size_t i=0; i<noOldNeighbours; ++i)
+ delete[] sendBuffers_[i];
+
+ delete[] sendBuffers_;
+ delete[] sendBufferSizes_;
+
+ // No need for the iterator tuples any more
+ iteratorsMap_.clear();
+
+ indexSet_.endResize();
+
+ delete[] oldNeighbours;
+
+ repairLocalIndexPointers(globalMap_, remoteIndices_, indexSet_);
+
+ oldMap_.clear();
+ globalMap_.clear();
+
+ // update the sequence number
+ remoteIndices_.sourceSeqNo_ = remoteIndices_.destSeqNo_ = indexSet_.seqNo();
+ }
+
+ template<typename T>
+ void IndicesSyncer<T>::packAndSend(int destination, char* buffer, std::size_t bufferSize, MPI_Request& request)
+ {
+ typedef typename ParallelIndexSet::const_iterator IndexIterator;
+
+ IndexIterator iEnd = indexSet_.end();
+ int bpos = 0;
+ int published = 0;
+ int pairs = 0;
+
+ assert(checkReset());
+
+ // Pack the number of indices we publish
+ MPI_Pack(&(infoSend_[destination].publish), 1, MPI_INT, buffer, bufferSize, &bpos,
+ remoteIndices_.communicator());
+
+ for(IndexIterator index = indexSet_.begin(); index != iEnd; ++index) {
+ // Search for corresponding remote indices in all iterator tuples
+ typedef typename IteratorsMap::iterator Iterator;
+ Iterator iteratorsEnd = iteratorsMap_.end();
+
+ // advance all iterators to a position with global index >= index->global()
+ for(Iterator iterators = iteratorsMap_.begin(); iteratorsEnd != iterators; ++iterators) {
+ while(iterators->second.isNotAtEnd() &&
+ iterators->second.globalIndexPair().first < index->global())
+ ++(iterators->second);
+ assert(!iterators->second.isNotAtEnd() || iterators->second.globalIndexPair().first >= index->global());
+ }
+
+ // Add all remote indices positioned at global which were already present before calling sync
+ // to the message.
+ // Count how many remote indices we will send
+ int indices = 0;
+ bool knownRemote = false; // Is the remote process supposed to know this index?
+
+ for(Iterator iterators = iteratorsMap_.begin(); iteratorsEnd != iterators; ++iterators)
+ {
+ std::pair<GlobalIndex,Attribute> p;
+ if (iterators->second.isNotAtEnd())
+ {
+ p = iterators->second.globalIndexPair();
+ }
+
+ if(iterators->second.isNotAtEnd() && iterators->second.isOld()
+ && iterators->second.globalIndexPair().first == index->global()) {
+ indices++;
+ if(destination == iterators->first)
+ knownRemote = true;
+ }
+ }
+
+ if(!knownRemote)
+ // We do not need to send any indices
+ continue;
+
+ Dune::dverb<<rank_<<": sending "<<indices<<" for index "<<index->global()<<" to "<<destination<<std::endl;
+
+
+ // Pack the global index, the attribute and the number
+ MPI_Pack(const_cast<GlobalIndex*>(&(index->global())), 1, MPITraits<GlobalIndex>::getType(), buffer, bufferSize, &bpos,
+ remoteIndices_.communicator());
+
+ char attr = index->local().attribute();
+ MPI_Pack(&attr, 1, MPI_CHAR, buffer, bufferSize, &bpos,
+ remoteIndices_.communicator());
+
+ // Pack the number of remote indices we send.
+ MPI_Pack(&indices, 1, MPI_INT, buffer, bufferSize, &bpos,
+ remoteIndices_.communicator());
+
+ // Pack the information about the remote indices
+ for(Iterator iterators = iteratorsMap_.begin(); iteratorsEnd != iterators; ++iterators)
+ if(iterators->second.isNotAtEnd() && iterators->second.isOld()
+ && iterators->second.globalIndexPair().first == index->global()) {
+ int process = iterators->first;
+
+ ++pairs;
+ assert(pairs <= infoSend_[destination].pairs);
+ MPI_Pack(&process, 1, MPI_INT, buffer, bufferSize, &bpos,
+ remoteIndices_.communicator());
+ char attr = iterators->second.remoteIndex().attribute();
+
+ MPI_Pack(&attr, 1, MPI_CHAR, buffer, bufferSize, &bpos,
+ remoteIndices_.communicator());
+ --indices;
+ }
+ assert(indices==0);
+ ++published;
+ Dune::dvverb<<" (publish="<<published<<", pairs="<<pairs<<")"<<std::endl;
+ assert(published <= infoSend_[destination].publish);
+ }
+
+ // Make sure we send all expected entries
+ assert(published == infoSend_[destination].publish);
+ assert(pairs == infoSend_[destination].pairs);
+ resetIteratorsMap();
+
+ Dune::dverb << rank_<<": Sending message of "<<bpos<<" bytes to "<<destination<<std::endl;
+
+ MPI_Issend(buffer, bpos, MPI_PACKED, destination, 345, remoteIndices_.communicator(),&request);
+ }
+
+ template<typename T>
+ inline void IndicesSyncer<T>::insertIntoRemoteIndexList(int process,
+ const std::pair<GlobalIndex,Attribute>& globalPair,
+ char attribute)
+ {
+ Dune::dverb<<"Inserting from "<<process<<" "<<globalPair.first<<", "<<
+ globalPair.second<<" "<<attribute<<std::endl;
+
+ resetIteratorsMap();
+
+ // There might be cases where there no remote indices for that process yet
+ typename IteratorsMap::iterator found = iteratorsMap_.find(process);
+
+ if( found == iteratorsMap_.end() ) {
+ Dune::dverb<<"Discovered new neighbour "<<process<<std::endl;
+ RemoteIndexList* rlist = new RemoteIndexList();
+ remoteIndices_.remoteIndices_.insert(std::make_pair(process,std::make_pair(rlist,rlist)));
+ Iterators iterators = Iterators(*rlist, globalMap_[process], oldMap_[process]);
+ found = iteratorsMap_.insert(std::make_pair(process, iterators)).first;
+ }
+
+ Iterators& iterators = found->second;
+
+ // Search for the remote index
+ while(iterators.isNotAtEnd() && iterators.globalIndexPair() < globalPair) {
+ // Increment all iterators
+ ++iterators;
+
+ }
+
+ if(iterators.isAtEnd() || iterators.globalIndexPair() != globalPair) {
+ // The entry is not yet known
+ // Insert in the the list and do not change the first iterator.
+ iterators.insert(RemoteIndex(Attribute(attribute)),globalPair);
+ return;
+ }
+
+ // Global indices match
+ bool indexIsThere=false;
+ for(Iterators tmpIterators = iterators;
+ !tmpIterators.isAtEnd() && tmpIterators.globalIndexPair() == globalPair;
+ ++tmpIterators)
+ //entry already exists with the same attribute
+ if(tmpIterators.globalIndexPair().second == attribute) {
+ indexIsThere=true;
+ break;
+ }
+
+ if(!indexIsThere)
+ // The entry is not yet known
+ // Insert in the the list and do not change the first iterator.
+ iterators.insert(RemoteIndex(Attribute(attribute)),globalPair);
+ }
+
+ template<typename T>
+ template<typename T1>
+ void IndicesSyncer<T>::recvAndUnpack(T1& numberer)
+ {
+ typedef typename ParallelIndexSet::const_iterator IndexIterator;
+
+ IndexIterator iEnd = indexSet_.end();
+ IndexIterator index = indexSet_.begin();
+ int bpos = 0;
+ int publish;
+
+ assert(checkReset());
+
+ MPI_Status status;
+
+ // We have to determine the message size and source before the receive
+ MPI_Probe(MPI_ANY_SOURCE, 345, remoteIndices_.communicator(), &status);
+
+ int source=status.MPI_SOURCE;
+ int count;
+ MPI_Get_count(&status, MPI_PACKED, &count);
+
+ Dune::dvverb<<rank_<<": Receiving message from "<< source<<" with "<<count<<" bytes"<<std::endl;
+
+ if(count>receiveBufferSize_) {
+ receiveBufferSize_=count;
+ delete[] receiveBuffer_;
+ receiveBuffer_ = new char[receiveBufferSize_];
+ }
+
+ MPI_Recv(receiveBuffer_, count, MPI_PACKED, source, 345, remoteIndices_.communicator(), &status);
+
+ // How many global entries were published?
+ MPI_Unpack(receiveBuffer_, count, &bpos, &publish, 1, MPI_INT, remoteIndices_.communicator());
+
+ // Now unpack the remote indices and add them.
+ while(publish>0) {
+
+ // Unpack information about the local index on the source process
+ GlobalIndex global; // global index of the current entry
+ char sourceAttribute; // Attribute on the source process
+ int pairs;
+
+ MPI_Unpack(receiveBuffer_, count, &bpos, &global, 1, MPITraits<GlobalIndex>::getType(),
+ remoteIndices_.communicator());
+ MPI_Unpack(receiveBuffer_, count, &bpos, &sourceAttribute, 1, MPI_CHAR,
+ remoteIndices_.communicator());
+ MPI_Unpack(receiveBuffer_, count, &bpos, &pairs, 1, MPI_INT,
+ remoteIndices_.communicator());
+
+ // Insert the entry on the remote process to our
+ // remote index list
+ SLList<std::pair<int,Attribute> > sourceAttributeList;
+ sourceAttributeList.push_back(std::make_pair(source,Attribute(sourceAttribute)));
+#ifndef NDEBUG
+ bool foundSelf = false;
+#endif
+ Attribute myAttribute=Attribute();
+
+ // Unpack the remote indices
+ for(; pairs>0; --pairs) {
+ // Unpack the process id that knows the index
+ int process;
+ char attribute;
+ MPI_Unpack(receiveBuffer_, count, &bpos, &process, 1, MPI_INT,
+ remoteIndices_.communicator());
+ // Unpack the attribute
+ MPI_Unpack(receiveBuffer_, count, &bpos, &attribute, 1, MPI_CHAR,
+ remoteIndices_.communicator());
+
+ if(process==rank_) {
+#ifndef NDEBUG
+ foundSelf=true;
+#endif
+ myAttribute=Attribute(attribute);
+ // Now we know the local attribute of the global index
+ //Only add the index if it is unknown.
+ // Do we know that global index already?
+ IndexIterator pos = std::lower_bound(index, iEnd, IndexPair(global));
+
+ if(pos == iEnd || pos->global() != global) {
+ // no entry with this global index
+ indexSet_.add(global,
+ ParallelLocalIndex<Attribute>(numberer(global),
+ myAttribute, true));
+ Dune::dvverb << "Adding "<<global<<" "<<myAttribute<<std::endl;
+ continue;
+ }
+
+ // because of above the global indices match. Add only if the attribute is different
+ bool indexIsThere = false;
+ index=pos;
+
+ for(; pos->global()==global; ++pos)
+ if(pos->local().attribute() == myAttribute) {
+ Dune::dvverb<<"found "<<global<<" "<<myAttribute<<std::endl;
+ indexIsThere = true;
+ break;
+ }
+
+ if(!indexIsThere) {
+ indexSet_.add(global,
+ ParallelLocalIndex<Attribute>(numberer(global),
+ myAttribute, true));
+ Dune::dvverb << "Adding "<<global<<" "<<myAttribute<<std::endl;
+ }
+
+ }else{
+ sourceAttributeList.push_back(std::make_pair(process,Attribute(attribute)));
+ }
+ }
+ assert(foundSelf);
+ // Insert remote indices
+ typedef typename SLList<std::pair<int,Attribute> >::const_iterator Iter;
+ for(Iter i=sourceAttributeList.begin(), end=sourceAttributeList.end();
+ i!=end; ++i)
+ insertIntoRemoteIndexList(i->first, std::make_pair(global, myAttribute),
+ i->second);
+ --publish;
+ }
+
+ resetIteratorsMap();
+ }
+
+ template<typename T>
+ void IndicesSyncer<T>::resetIteratorsMap(){
+
+ // Reset iterators in all tuples.
+ typedef typename IteratorsMap::iterator Iterator;
+ typedef typename RemoteIndices::RemoteIndexMap::iterator
+ RemoteIterator;
+ typedef typename GlobalIndicesMap::iterator GlobalIterator;
+ typedef typename BoolMap::iterator BoolIterator;
+
+ const RemoteIterator remoteEnd = remoteIndices_.remoteIndices_.end();
+ Iterator iterators = iteratorsMap_.begin();
+ GlobalIterator global = globalMap_.begin();
+ BoolIterator added = oldMap_.begin();
+
+ for(RemoteIterator remote = remoteIndices_.remoteIndices_.begin();
+ remote != remoteEnd; ++remote, ++global, ++added, ++iterators) {
+ iterators->second.reset(*(remote->second.first), global->second, added->second);
+ }
+ }
+
+ template<typename T>
+ bool IndicesSyncer<T>::checkReset(const Iterators& iterators, RemoteIndexList& rList, GlobalIndexList& gList,
+ BoolList& bList){
+
+ if(get<0>(iterators.iterators_)!=rList.begin())
+ return false;
+ if(get<1>(iterators.iterators_)!=gList.begin())
+ return false;
+ if(get<2>(iterators.iterators_)!=bList.begin())
+ return false;
+ return true;
+ }
+
+
+ template<typename T>
+ bool IndicesSyncer<T>::checkReset(){
+
+ // Reset iterators in all tuples.
+ typedef typename IteratorsMap::iterator Iterator;
+ typedef typename RemoteIndices::RemoteIndexMap::iterator
+ RemoteIterator;
+ typedef typename GlobalIndicesMap::iterator GlobalIterator;
+ typedef typename BoolMap::iterator BoolIterator;
+
+ const RemoteIterator remoteEnd = remoteIndices_.remoteIndices_.end();
+ Iterator iterators = iteratorsMap_.begin();
+ GlobalIterator global = globalMap_.begin();
+ BoolIterator added = oldMap_.begin();
+ bool ret = true;
+
+ for(RemoteIterator remote = remoteIndices_.remoteIndices_.begin();
+ remote != remoteEnd; ++remote, ++global, ++added, ++iterators) {
+ if(!checkReset(iterators->second, *(remote->second.first), global->second,
+ added->second))
+ ret=false;
+ }
+ return ret;
+ }
+}
+
+#endif
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+#ifndef DUNE_INTERFACE_HH
+#define DUNE_INTERFACE_HH
+
+#if HAVE_MPI
+
+#include "remoteindices.hh"
+#include <dune/common/enumset.hh>
+
+namespace Dune
+{
+ /** @addtogroup Common_Parallel
+ *
+ * @{
+ */
+ /**
+ * @file
+ * @brief Provides classes for building the communication
+ * interface between remote indices.
+ * @author Markus Blatt
+ */
+
+ /** @} */
+ /**
+ * @brief Base class of all classes representing a communication
+ * interface.
+ *
+ * It provides an generic utility method for building the interface
+ * for a set of remote indices.
+ */
+ class InterfaceBuilder
+ {
+ public:
+ class RemotexIndicesStateError : public Exception
+ {};
+
+ virtual ~InterfaceBuilder()
+ {}
+
+ protected:
+ /**
+ * @brief Not for public use.
+ */
+ InterfaceBuilder()
+ {}
+
+ /**
+ * @brief Builds the interface between remote processes.
+ *
+ *
+ * The types T1 and T2 are classes representing a set of
+ * enumeration values of type InterfaceBuilder::Attribute. They have to provide
+ * a (static) method
+ * \code
+ * bool contains(Attribute flag) const;
+ * \endcode
+ * for checking whether the set contains a specfic flag.
+ * This functionality is for example provided the classes
+ * EnumItem, EnumRange and Combine.
+ *
+ * If the template parameter send is true the sending side of
+ * the interface will be built, otherwise the information for
+ * receiving will be built.
+ *
+ *
+ * If the template parameter send is true we create interface for sending
+ * in a forward communication.
+ *
+ * @param remoteIndices The indices known to remote processes.
+ * @param sourceFlags The set of flags marking source indices.
+ * @param destFlags The setof flags markig destination indices.
+ * @param functor A functor for callbacks. It should provide the
+ * following methods:
+ * \code
+ * // Reserve memory for the interface to processor proc. The interface
+ * // has to hold size entries
+ * void reserve(int proc, int size);
+ *
+ * // Add an entry to the interface
+ * // We will send/receive size entries at index local to process proc
+ * void add(int proc, int local);
+ * \endcode
+ */
+ template<class R, class T1, class T2, class Op, bool send>
+ void buildInterface (const R& remoteIndices,
+ const T1& sourceFlags, const T2& destFlags,
+ Op& functor) const;
+ };
+
+ /**
+ * @brief Information describing an interface.
+ *
+ * This class is used for temporary gathering information
+ * about the interface needed for actually building it. It
+ * is used be class Interface as functor for InterfaceBuilder::build.
+ */
+ class InterfaceInformation
+ {
+
+ public:
+
+ /**
+ * @brief Get the number of entries in the interface.
+ */
+ size_t size() const
+ {
+ return size_;
+ }
+ /**
+ * @brief Get the local index for an entry.
+ * @param i The index of the entry.
+ */
+ std::size_t& operator[](size_t i)
+ {
+ assert(i<size_);
+ return indices_[i];
+ }
+ /**
+ * @brief Get the local index for an entry.
+ * @param i The index of the entry.
+ */
+ std::size_t operator[](size_t i) const
+ {
+ assert(i<size_);
+ return indices_[i];
+ }
+ /**
+ * @brief Reserve space for a number of entries.
+ * @param size The maximum number of entries to hold.
+ */
+ void reserve(size_t size)
+ {
+ indices_ = new std::size_t[size];
+ maxSize_ = size;
+
+ }
+ /**
+ * brief Frees allocated memory.
+ */
+ void free()
+ {
+ if(indices_)
+ delete[] indices_;
+ maxSize_ = 0;
+ size_=0;
+ indices_=0;
+ }
+ /**
+ * @brief Add a new index to the interface.
+ */
+ void add(std::size_t index)
+ {
+ assert(size_<maxSize_);
+ indices_[size_++]=index;
+ }
+
+ InterfaceInformation()
+ : size_(0), maxSize_(0), indices_(0)
+ {}
+
+ virtual ~InterfaceInformation()
+ {}
+
+ bool operator!=(const InterfaceInformation& o) const
+ {
+ return !operator==(o);
+ }
+
+ bool operator==(const InterfaceInformation& o) const
+ {
+ if(size_!=o.size_)
+ return false;
+ for(std::size_t i=0; i< size_; ++i)
+ if(indices_[i]!=o.indices_[i])
+ return false;
+ return true;
+ }
+
+ private:
+ /**
+ * @brief The number of entries in the interface.
+ */
+ size_t size_;
+ /**
+ * @brief The maximum number of indices we can hold.
+ */
+ size_t maxSize_;
+ /**
+ * @brief The local indices of the interface.
+ */
+ std::size_t* indices_;
+ };
+
+ /** @addtogroup Common_Parallel
+ *
+ * @{
+ */
+
+ /**
+ * @brief Communication interface between remote and local indices.
+ *
+ * Describes the communication interface between
+ * indices on the local process and those on remote processes.
+ */
+ class Interface : public InterfaceBuilder
+ {
+
+ public:
+ /**
+ * @brief The type of the map form process number to InterfaceInformation for
+ * sending and receiving to and from it.
+ */
+ typedef std::map<int,std::pair<InterfaceInformation,InterfaceInformation> > InformationMap;
+
+ /**
+ * @brief Builds the interface.
+ *
+ * The types T1 and T2 are classes representing a set of
+ * enumeration values of type Interface::Attribute. They have to provide
+ * a (static) method
+ * \code
+ * bool contains(Attribute flag) const;
+ * \endcode
+ * for checking whether the set contains a specfic flag.
+ * This functionality is for example provided the classes
+ * EnumItem, EnumRange and Combine.
+ * @param remoteIndices The indices known to remote processes.
+ * @param sourceFlags The set of flags marking indices we send from.
+ * @param destFlags The set of flags marking indices we receive for.
+ */
+ template<typename R, typename T1, typename T2>
+ void build(const R& remoteIndices, const T1& sourceFlags,
+ const T2& destFlags);
+
+ /**
+ * @brief Frees memory allocated during the build.
+ */
+ void free();
+
+ /**
+ * @brief Get the MPI Communicator.
+ */
+ MPI_Comm communicator() const;
+
+ /**
+ * @brief Get information about the interfaces.
+ *
+ * @return Map of the interfaces.
+ * The key of the map is the process number and the value
+ * is the information pair (first the send and then the receive
+ * information).
+ */
+ const InformationMap& interfaces() const;
+
+ Interface(MPI_Comm comm)
+ : communicator_(comm), interfaces_()
+ {}
+
+ Interface()
+ : communicator_(MPI_COMM_NULL), interfaces_()
+ {}
+
+ /**
+ * @brief Print the interface to std::out for debugging.
+ */
+ void print() const;
+
+ bool operator!=(const Interface& o) const
+ {
+ return ! operator==(o);
+ }
+
+ bool operator==(const Interface& o) const
+ {
+ if(communicator_!=o.communicator_)
+ return false;
+ if(interfaces_.size()!=o.interfaces_.size())
+ return false;
+ typedef InformationMap::const_iterator MIter;
+
+ for(MIter m=interfaces_.begin(), om=o.interfaces_.begin();
+ m!=interfaces_.end(); ++m, ++om)
+ {
+ if(om->first!=m->first)
+ return false;
+ if(om->second.first!=om->second.first)
+ return false;
+ if(om->second.second!=om->second.second)
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @brief Destructor.
+ */
+ virtual ~Interface();
+
+ void strip();
+ protected:
+
+ /**
+ * @brief Get information about the interfaces.
+ *
+ * @return Map of the interfaces.
+ * The key of the map is the process number and the value
+ * is the information pair (first the send and then the receive
+ * information).
+ */
+ InformationMap& interfaces();
+
+ /** @brief The MPI communicator we use. */
+ MPI_Comm communicator_;
+
+ private:
+ /**
+ * @brief Information about the interfaces.
+ *
+ * The key of the map is the process number and the value
+ * is the information pair (first the send and then the receive
+ * information).
+ */
+ InformationMap interfaces_;
+
+ template<bool send>
+ class InformationBuilder
+ {
+ public:
+ InformationBuilder(InformationMap& interfaces)
+ : interfaces_(interfaces)
+ {}
+
+ void reserve(int proc, int size)
+ {
+ if(send)
+ interfaces_[proc].first.reserve(size);
+ else
+ interfaces_[proc].second.reserve(size);
+ }
+ void add(int proc, std::size_t local)
+ {
+ if(send) {
+ interfaces_[proc].first.add(local);
+ }else{
+ interfaces_[proc].second.add(local);
+ }
+ }
+
+ private:
+ InformationMap& interfaces_;
+ };
+ };
+
+ template<class R, class T1, class T2, class Op, bool send>
+ void InterfaceBuilder::buildInterface(const R& remoteIndices, const T1& sourceFlags, const T2& destFlags, Op& interfaceInformation) const
+ {
+
+ if(!remoteIndices.isSynced())
+ DUNE_THROW(RemotexIndicesStateError,"RemoteIndices is not in sync with the index set. Call RemoteIndices::rebuild first!");
+ // Allocate the memory for the data type construction.
+ typedef R RemoteIndices;
+ typedef typename RemoteIndices::RemoteIndexMap::const_iterator const_iterator;
+
+ const const_iterator end=remoteIndices.end();
+
+ int rank;
+
+ MPI_Comm_rank(remoteIndices.communicator(), &rank);
+
+ // Allocate memory for the type construction.
+ for(const_iterator process=remoteIndices.begin(); process != end; ++process) {
+ // Messure the number of indices send to the remote process first
+ int size=0;
+ typedef typename RemoteIndices::RemoteIndexList::const_iterator RemoteIterator;
+ const RemoteIterator remoteEnd = send ? process->second.first->end() :
+ process->second.second->end();
+ RemoteIterator remote = send ? process->second.first->begin() : process->second.second->begin();
+
+ while(remote!=remoteEnd) {
+ if( send ? destFlags.contains(remote->attribute()) :
+ sourceFlags.contains(remote->attribute())) {
+
+ // do we send the index?
+ if( send ? sourceFlags.contains(remote->localIndexPair().local().attribute()) :
+ destFlags.contains(remote->localIndexPair().local().attribute()))
+ ++size;
+ }
+ ++remote;
+ }
+ interfaceInformation.reserve(process->first, size);
+ }
+
+ // compare the local and remote indices and set up the types
+
+ for(const_iterator process=remoteIndices.begin(); process != end; ++process) {
+ typedef typename RemoteIndices::RemoteIndexList::const_iterator RemoteIterator;
+ const RemoteIterator remoteEnd = send ? process->second.first->end() :
+ process->second.second->end();
+ RemoteIterator remote = send ? process->second.first->begin() : process->second.second->begin();
+
+ while(remote!=remoteEnd) {
+ if( send ? destFlags.contains(remote->attribute()) :
+ sourceFlags.contains(remote->attribute())) {
+ // do we send the index?
+ if( send ? sourceFlags.contains(remote->localIndexPair().local().attribute()) :
+ destFlags.contains(remote->localIndexPair().local().attribute()))
+ interfaceInformation.add(process->first,remote->localIndexPair().local().local());
+ }
+ ++remote;
+ }
+ }
+ }
+
+ inline MPI_Comm Interface::communicator() const
+ {
+ return communicator_;
+
+ }
+
+
+ inline const std::map<int,std::pair<InterfaceInformation,InterfaceInformation> >& Interface::interfaces() const
+ {
+ return interfaces_;
+ }
+
+ inline std::map<int,std::pair<InterfaceInformation,InterfaceInformation> >& Interface::interfaces()
+ {
+ return interfaces_;
+ }
+
+ inline void Interface::print() const
+ {
+ typedef InformationMap::const_iterator const_iterator;
+ const const_iterator end=interfaces_.end();
+ int rank;
+ MPI_Comm_rank(communicator(), &rank);
+
+ for(const_iterator infoPair=interfaces_.begin(); infoPair!=end; ++infoPair) {
+ {
+ std::cout<<rank<<": send for process "<<infoPair->first<<": ";
+ const InterfaceInformation& info(infoPair->second.first);
+ for(size_t i=0; i < info.size(); i++)
+ std::cout<<info[i]<<" ";
+ std::cout<<std::endl;
+ } {
+
+ std::cout<<rank<<": receive for process "<<infoPair->first<<": ";
+ const InterfaceInformation& info(infoPair->second.second);
+ for(size_t i=0; i < info.size(); i++)
+ std::cout<<info[i]<<" ";
+ std::cout<<std::endl;
+ }
+
+ }
+ }
+
+ template<typename R, typename T1, typename T2>
+ inline void Interface::build(const R& remoteIndices, const T1& sourceFlags,
+ const T2& destFlags)
+ {
+ communicator_=remoteIndices.communicator();
+
+ assert(interfaces_.empty());
+
+ // Build the send interface
+ InformationBuilder<true> sendInformation(interfaces_);
+ this->template buildInterface<R,T1,T2,InformationBuilder<true>,true>(remoteIndices, sourceFlags,
+ destFlags, sendInformation);
+
+ // Build the receive interface
+ InformationBuilder<false> recvInformation(interfaces_);
+ this->template buildInterface<R,T1,T2,InformationBuilder<false>,false>(remoteIndices,sourceFlags,
+ destFlags, recvInformation);
+ strip();
+ }
+ inline void Interface::strip()
+ {
+ typedef InformationMap::iterator const_iterator;
+ for(const_iterator interfacePair = interfaces_.begin(); interfacePair != interfaces_.end();)
+ if(interfacePair->second.first.size()==0 && interfacePair->second.second.size()==0) {
+ interfacePair->second.first.free();
+ interfacePair->second.second.free();
+ const_iterator toerase=interfacePair++;
+ interfaces_.erase(toerase);
+ }else
+ ++interfacePair;
+ }
+
+ inline void Interface::free()
+ {
+ typedef InformationMap::iterator iterator;
+ typedef InformationMap::const_iterator const_iterator;
+ const const_iterator end = interfaces_.end();
+ for(iterator interfacePair = interfaces_.begin(); interfacePair != end; ++interfacePair) {
+ interfacePair->second.first.free();
+ interfacePair->second.second.free();
+ }
+ interfaces_.clear();
+ }
+
+ inline Interface::~Interface()
+ {
+ free();
+ }
+ /** @} */
+}
+
+namespace std
+{
+ inline ostream& operator<<(ostream& os, const Dune::Interface& interface)
+ {
+ typedef Dune::Interface::InformationMap InfoMap;
+ typedef InfoMap::const_iterator Iter;
+ for(Iter i=interface.interfaces().begin(), end = interface.interfaces().end();
+ i!=end; ++i)
+ {
+ os<<i->first<<": [ source=[";
+ for(std::size_t j=0; j < i->second.first.size(); ++j)
+ os<<i->second.first[j]<<" ";
+ os<<"] size="<<i->second.first.size()<<", target=[";
+ for(std::size_t j=0; j < i->second.second.size(); ++j)
+ os<<i->second.second[j]<<" ";
+ os<<"] size="<<i->second.second.size()<<"\n";
+ }
+ return os;
+ }
+} // end namespace std
+#endif // HAVE_MPI
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+
+#ifndef DUNE_COMMON_LOCALINDEX_HH
+#define DUNE_COMMON_LOCALINDEX_HH
+
+#include <cstddef>
+
+namespace Dune
+{
+
+
+ /** @addtogroup Common_Parallel
+ *
+ * @{
+ */
+ /**
+ * @file
+ * @brief Provides classes for use as the local index in ParallelIndexSet.
+ * @author Markus Blatt
+ */
+ /**
+ * @brief The states avaiable for the local indices.
+ * @see LocalIndex::state()
+ */
+ enum LocalIndexState {VALID, DELETED};
+
+
+ /**
+ * @brief An index present on the local process.
+ */
+ class LocalIndex
+ {
+ public:
+ /**
+ * @brief Constructor.
+ * known to other processes.
+ */
+ LocalIndex() :
+ localIndex_(0), state_(VALID){}
+
+
+ /**
+ * @brief Constructor.
+ * @param index The value of the index.
+ */
+ LocalIndex(std::size_t index) :
+ localIndex_(index), state_(VALID){}
+ /**
+ * @brief get the local index.
+ * @return The local index.
+ */
+ inline const std::size_t& local() const;
+
+ /**
+ * @brief Convert to the local index represented by an int.
+ */
+ inline operator std::size_t() const;
+
+ /**
+ * @brief Assign a new local index.
+ *
+ * @param index The new local index.
+ */
+ inline LocalIndex& operator=(std::size_t index);
+
+ /**
+ * @brief Get the state.
+ * @return The state.
+ */
+ inline LocalIndexState state() const;
+
+ /**
+ * @brief Set the state.
+ * @param state The state to set.
+ */
+ inline void setState(LocalIndexState state);
+
+ private:
+ /** @brief The local index. */
+ std::size_t localIndex_;
+
+ /**
+ * @brief The state of the index.
+ *
+ * Has to be one of LocalIndexState!
+ * @see LocalIndexState.
+ */
+ char state_;
+
+ };
+
+
+
+ inline const std::size_t& LocalIndex::local() const {
+ return localIndex_;
+ }
+
+ inline LocalIndex::operator std::size_t() const {
+ return localIndex_;
+ }
+
+ inline LocalIndex& LocalIndex::operator=(std::size_t index){
+ localIndex_ = index;
+ return *this;
+ }
+
+ inline LocalIndexState LocalIndex::state() const {
+ return static_cast<LocalIndexState>(state_);
+ }
+
+ inline void LocalIndex::setState(LocalIndexState state){
+ state_ = static_cast<char>(state);
+ }
+
+ /** @} */
+
+} // namespace Dune
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_MPICOLLECTIVECOMMUNICATION_HH
+#define DUNE_MPICOLLECTIVECOMMUNICATION_HH
+
+/*!
+ \file
+ \brief Implements an utility class that provides
+ MPI's collective communication methods.
+
+ \ingroup ParallelCommunication
+ */
+
+#include <iostream>
+#include <complex>
+#include <algorithm>
+#include <functional>
+
+#include <dune/common/exceptions.hh>
+#include <dune/common/binaryfunctions.hh>
+#include <dune/common/shared_ptr.hh>
+
+#include "collectivecommunication.hh"
+#include "mpitraits.hh"
+
+#if HAVE_MPI
+// MPI header
+#include <mpi.h>
+
+namespace Dune
+{
+
+ //=======================================================
+ // use singleton pattern and template specialization to
+ // generate MPI operations
+ //=======================================================
+
+ template<typename Type, typename BinaryFunction>
+ class Generic_MPI_Op
+ {
+
+ public:
+ static MPI_Op get ()
+ {
+ if (!op)
+ {
+ op = shared_ptr<MPI_Op>(new MPI_Op);
+ MPI_Op_create((void (*)(void*, void*, int*, MPI_Datatype*))&operation,true,op.get());
+ }
+ return *op;
+ }
+ private:
+ static void operation (Type *in, Type *inout, int *len, MPI_Datatype *dptr)
+ {
+ BinaryFunction func;
+
+ for (int i=0; i< *len; ++i, ++in, ++inout) {
+ Type temp;
+ temp = func(*in, *inout);
+ *inout = temp;
+ }
+ }
+ Generic_MPI_Op () {}
+ Generic_MPI_Op (const Generic_MPI_Op& ) {}
+ static shared_ptr<MPI_Op> op;
+ };
+
+
+ template<typename Type, typename BinaryFunction>
+ shared_ptr<MPI_Op> Generic_MPI_Op<Type,BinaryFunction>::op = shared_ptr<MPI_Op>(static_cast<MPI_Op*>(0));
+
+#define ComposeMPIOp(type,func,op) \
+ template<> \
+ class Generic_MPI_Op<type, func<type> >{ \
+ public:\
+ static MPI_Op get(){ \
+ return op; \
+ } \
+ private:\
+ Generic_MPI_Op () {}\
+ Generic_MPI_Op (const Generic_MPI_Op & ) {}\
+ }
+
+
+ ComposeMPIOp(char, std::plus, MPI_SUM);
+ ComposeMPIOp(unsigned char, std::plus, MPI_SUM);
+ ComposeMPIOp(short, std::plus, MPI_SUM);
+ ComposeMPIOp(unsigned short, std::plus, MPI_SUM);
+ ComposeMPIOp(int, std::plus, MPI_SUM);
+ ComposeMPIOp(unsigned int, std::plus, MPI_SUM);
+ ComposeMPIOp(long, std::plus, MPI_SUM);
+ ComposeMPIOp(unsigned long, std::plus, MPI_SUM);
+ ComposeMPIOp(float, std::plus, MPI_SUM);
+ ComposeMPIOp(double, std::plus, MPI_SUM);
+ ComposeMPIOp(long double, std::plus, MPI_SUM);
+
+ ComposeMPIOp(char, std::multiplies, MPI_PROD);
+ ComposeMPIOp(unsigned char, std::multiplies, MPI_PROD);
+ ComposeMPIOp(short, std::multiplies, MPI_PROD);
+ ComposeMPIOp(unsigned short, std::multiplies, MPI_PROD);
+ ComposeMPIOp(int, std::multiplies, MPI_PROD);
+ ComposeMPIOp(unsigned int, std::multiplies, MPI_PROD);
+ ComposeMPIOp(long, std::multiplies, MPI_PROD);
+ ComposeMPIOp(unsigned long, std::multiplies, MPI_PROD);
+ ComposeMPIOp(float, std::multiplies, MPI_PROD);
+ ComposeMPIOp(double, std::multiplies, MPI_PROD);
+ ComposeMPIOp(long double, std::multiplies, MPI_PROD);
+
+ ComposeMPIOp(char, Min, MPI_MIN);
+ ComposeMPIOp(unsigned char, Min, MPI_MIN);
+ ComposeMPIOp(short, Min, MPI_MIN);
+ ComposeMPIOp(unsigned short, Min, MPI_MIN);
+ ComposeMPIOp(int, Min, MPI_MIN);
+ ComposeMPIOp(unsigned int, Min, MPI_MIN);
+ ComposeMPIOp(long, Min, MPI_MIN);
+ ComposeMPIOp(unsigned long, Min, MPI_MIN);
+ ComposeMPIOp(float, Min, MPI_MIN);
+ ComposeMPIOp(double, Min, MPI_MIN);
+ ComposeMPIOp(long double, Min, MPI_MIN);
+
+ ComposeMPIOp(char, Max, MPI_MAX);
+ ComposeMPIOp(unsigned char, Max, MPI_MAX);
+ ComposeMPIOp(short, Max, MPI_MAX);
+ ComposeMPIOp(unsigned short, Max, MPI_MAX);
+ ComposeMPIOp(int, Max, MPI_MAX);
+ ComposeMPIOp(unsigned int, Max, MPI_MAX);
+ ComposeMPIOp(long, Max, MPI_MAX);
+ ComposeMPIOp(unsigned long, Max, MPI_MAX);
+ ComposeMPIOp(float, Max, MPI_MAX);
+ ComposeMPIOp(double, Max, MPI_MAX);
+ ComposeMPIOp(long double, Max, MPI_MAX);
+
+#undef ComposeMPIOp
+
+
+ //=======================================================
+ // use singleton pattern and template specialization to
+ // generate MPI operations
+ //=======================================================
+
+ /*! \brief Specialization of CollectiveCommunication for MPI
+ \ingroup ParallelCommunication
+ */
+ template<>
+ class CollectiveCommunication<MPI_Comm>
+ {
+ public:
+ //! Instantiation using a MPI communicator
+ CollectiveCommunication (const MPI_Comm& c)
+ : communicator(c)
+ {
+ if(communicator!=MPI_COMM_NULL) {
+ MPI_Comm_rank(communicator,&me);
+ MPI_Comm_size(communicator,&procs);
+ }else{
+ procs=0;
+ me=-1;
+ }
+ }
+
+ //! @copydoc CollectiveCommunication::rank
+ int rank () const
+ {
+ return me;
+ }
+
+ //! @copydoc CollectiveCommunication::size
+ int size () const
+ {
+ return procs;
+ }
+
+ //! @copydoc CollectiveCommunication::sum
+ template<typename T>
+ T sum (T& in) const // MPI does not know about const :-(
+ {
+ T out;
+ allreduce<std::plus<T> >(&in,&out,1);
+ return out;
+ }
+
+ //! @copydoc CollectiveCommunication::sum
+ template<typename T>
+ int sum (T* inout, int len) const
+ {
+ return allreduce<std::plus<T> >(inout,len);
+ }
+
+ //! @copydoc CollectiveCommunication::prod
+ template<typename T>
+ T prod (T& in) const // MPI does not know about const :-(
+ {
+ T out;
+ allreduce<std::multiplies<T> >(&in,&out,1);
+ return out;
+ }
+
+ //! @copydoc CollectiveCommunication::prod
+ template<typename T>
+ int prod (T* inout, int len) const
+ {
+ return allreduce<std::multiplies<T> >(inout,len);
+ }
+
+ //! @copydoc CollectiveCommunication::min
+ template<typename T>
+ T min (T& in) const // MPI does not know about const :-(
+ {
+ T out;
+ allreduce<Min<T> >(&in,&out,1);
+ return out;
+ }
+
+ //! @copydoc CollectiveCommunication::min
+ template<typename T>
+ int min (T* inout, int len) const
+ {
+ return allreduce<Min<T> >(inout,len);
+ }
+
+
+ //! @copydoc CollectiveCommunication::max
+ template<typename T>
+ T max (T& in) const // MPI does not know about const :-(
+ {
+ T out;
+ allreduce<Max<T> >(&in,&out,1);
+ return out;
+ }
+
+ //! @copydoc CollectiveCommunication::max
+ template<typename T>
+ int max (T* inout, int len) const
+ {
+ return allreduce<Max<T> >(inout,len);
+ }
+
+ //! @copydoc CollectiveCommunication::barrier
+ int barrier () const
+ {
+ return MPI_Barrier(communicator);
+ }
+
+ //! @copydoc CollectiveCommunication::broadcast
+ template<typename T>
+ int broadcast (T* inout, int len, int root) const
+ {
+ return MPI_Bcast(inout,len,MPITraits<T>::getType(),root,communicator);
+ }
+
+ //! @copydoc CollectiveCommunication::gather()
+ //! @note out must have space for P*len elements
+ template<typename T>
+ int gather (T* in, T* out, int len, int root) const
+ {
+ return MPI_Gather(in,len,MPITraits<T>::getType(),
+ out,len,MPITraits<T>::getType(),
+ root,communicator);
+ }
+
+ //! @copydoc CollectiveCommunication::scatter()
+ //! @note out must have space for P*len elements
+ template<typename T>
+ int scatter (T* send, T* recv, int len, int root) const
+ {
+ return MPI_Scatter(send,len,MPITraits<T>::getType(),
+ recv,len,MPITraits<T>::getType(),
+ root,communicator);
+ }
+
+ operator MPI_Comm () const
+ {
+ return communicator;
+ }
+
+ //! @copydoc CollectiveCommunication::allgather()
+ template<typename T, typename T1>
+ int allgather(T* sbuf, int count, T1* rbuf) const
+ {
+ return MPI_Allgather(sbuf, count, MPITraits<T>::getType(),
+ rbuf, count, MPITraits<T1>::getType(),
+ communicator);
+ }
+
+ //! @copydoc CollectiveCommunication::allreduce(Type* inout,int len) const
+ template<typename BinaryFunction, typename Type>
+ int allreduce(Type* inout, int len) const
+ {
+ Type* out = new Type[len];
+ int ret = allreduce<BinaryFunction>(inout,out,len);
+ std::copy(out, out+len, inout);
+ delete[] out;
+ return ret;
+ }
+
+ //! @copydoc CollectiveCommunication::allreduce(Type* in,Type* out,int len) const
+ template<typename BinaryFunction, typename Type>
+ int allreduce(Type* in, Type* out, int len) const
+ {
+ return MPI_Allreduce(in, out, len, MPITraits<Type>::getType(),
+ (Generic_MPI_Op<Type, BinaryFunction>::get()),communicator);
+ }
+
+ private:
+ MPI_Comm communicator;
+ int me;
+ int procs;
+ };
+} // namespace dune
+
+#endif
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+
+/**
+ * @file
+ * @brief Implements a MPIGuard which detects an error on a remote process
+ * @author Christian Engwer
+ * @ingroup ParallelCommunication
+ */
+
+#ifndef DUNE_COMMON_MPIGUARD_HH
+#define DUNE_COMMON_MPIGUARD_HH
+
+#include "mpihelper.hh"
+#include "collectivecommunication.hh"
+#include "mpicollectivecommunication.hh"
+#include <dune/common/exceptions.hh>
+
+namespace Dune
+{
+
+#ifndef DOXYGEN
+
+ /*
+ Interface class for the communication needed by MPIGuard
+ */
+ struct GuardCommunicator
+ {
+ // cleanup
+ virtual ~GuardCommunicator() {};
+ // all the communication methods we need
+ virtual int rank() = 0;
+ virtual int size() = 0;
+ virtual int sum(int i) = 0;
+ // create a new GuardCommunicator pointer
+ template <class C>
+ static GuardCommunicator * create(const C & c);
+ };
+
+ namespace {
+ /*
+ templated implementation of different communication classes
+ */
+ // the default class will always fail, due to the missing implementation of "sum"
+ template <class Imp>
+ struct GenericGuardCommunicator
+ : public GuardCommunicator
+ {};
+ // specialization for CollectiveCommunication
+ template <class T>
+ struct GenericGuardCommunicator< CollectiveCommunication<T> >
+ : public GuardCommunicator
+ {
+ const CollectiveCommunication<T> comm;
+ GenericGuardCommunicator(const CollectiveCommunication<T> & c) :
+ comm(c) {}
+ virtual int rank() { return comm.rank(); };
+ virtual int size() { return comm.size(); };
+ virtual int sum(int i) { return comm.sum(i); }
+ };
+
+#if HAVE_MPI
+ // specialization for MPI_Comm
+ template <>
+ struct GenericGuardCommunicator<MPI_Comm>
+ : public GenericGuardCommunicator< CollectiveCommunication<MPI_Comm> >
+ {
+ GenericGuardCommunicator(const MPI_Comm & c) :
+ GenericGuardCommunicator< CollectiveCommunication<MPI_Comm> >(
+ CollectiveCommunication<MPI_Comm>(c)) {}
+ };
+#endif
+ } // anonymous namespace
+
+ template<class C>
+ GuardCommunicator * GuardCommunicator::create(const C & comm)
+ {
+ return new GenericGuardCommunicator<C>(comm);
+ }
+#endif
+
+ /*! @brief This exception is thrown if the MPIGuard detects an error on a remote process
+ @ingroup ParallelCommunication
+ */
+ class MPIGuardError : public ParallelError {};
+
+ /*! @brief detects a thrown exception and communicates to all other processes
+ @ingroup ParallelCommunication
+
+ @code
+ {
+ MPIGuard guard(...);
+
+ do_something();
+
+ // tell the guard that you successfully passed a critical operation
+ guard.finalize();
+ // reactivate the guard for the next critical operation
+ guard.reactivate();
+
+ int result = do_something_else();
+
+ // tell the guard the result of your operation
+ guard.finalize(result == success);
+ }
+ @endcode
+
+ You create a MPIGuard object. If an exception is risen on a
+ process the MPIGuard detects the exception, because the finalize
+ method was not called. when reaching the finalize call all
+ other processes are informed that an error occured and the
+ MPIGuard throws an exception of type MPIGuardError.
+
+ @note You can initialize the MPIGuard from different types of communication objects:
+ - MPIHelper
+ - CollectiveCommunication
+ - MPI_Comm
+ */
+ class MPIGuard
+ {
+ GuardCommunicator * comm_;
+ bool active_;
+
+ // we don't want to copy this class
+ MPIGuard (const MPIGuard &);
+
+ public:
+ /*! @brief create an MPIGuard operating on the Communicator of the global Dune::MPIHelper
+
+ @param active should the MPIGuard be active upon creation?
+ */
+ MPIGuard (bool active=true) :
+ comm_(GuardCommunicator::create(
+ MPIHelper::getCollectiveCommunication())),
+ active_(active)
+ {}
+
+ /*! @brief create an MPIGuard operating on the Communicator of a special Dune::MPIHelper m
+
+ @param m a reference to an MPIHelper
+ @param active should the MPIGuard be active upon creation?
+ */
+ MPIGuard (MPIHelper & m, bool active=true) :
+ comm_(GuardCommunicator::create(
+ m.getCollectiveCommunication())),
+ active_(active)
+ {}
+
+ /*! @brief create an MPIGuard operating on an arbitrary communicator.
+
+ Supported types for the communication object are:
+ - MPIHelper
+ - CollectiveCommunication
+ - MPI_Comm
+
+ @param comm reference to a communication object
+ @param active should the MPIGuard be active upon creation?
+ */
+ template <class C>
+ MPIGuard (const C & comm, bool active=true) :
+ comm_(GuardCommunicator::create(comm)),
+ active_(active)
+ {}
+
+ /*! @brief destroy the guard and check for undetected exceptions
+ */
+ ~MPIGuard()
+ {
+ if (active_)
+ {
+ active_ = false;
+ finalize(false);
+ }
+ delete comm_;
+ }
+
+ /*! @brief reactivate the guard.
+
+ If the guard is still active finalize(true) is called first.
+ */
+ void reactivate() {
+ if (active_ == true)
+ finalize();
+ active_ = true;
+ }
+
+ /*! @brief stop the guard.
+
+ If no success parameter is passed, the guard assumes that
+ everything worked as planned. All errors are communicated
+ and an exception of type MPIGuardError is thrown if an error
+ (or exception) occured on any of the processors in the
+ communicator.
+
+ @param success inform the guard about possible errors
+ */
+ void finalize(bool success = true)
+ {
+ int result = success ? 0 : 1;
+ bool was_active = active_;
+ active_ = false;
+ result = comm_->sum(result);
+ if (result>0 && was_active)
+ {
+ DUNE_THROW(MPIGuardError, "Terminating process "
+ << comm_->rank() << " due to "
+ << result << " remote error(s)");
+ }
+ }
+ };
+
+}
+
+#endif // DUNE_COMMON_MPIGUARD_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id: $
+#ifndef DUNE_MPIHELPER
+#define DUNE_MPIHELPER
+
+#include <cassert>
+#include "collectivecommunication.hh"
+#if HAVE_MPI
+#include "mpi.h"
+#include "mpicollectivecommunication.hh"
+#endif
+
+#include <dune/common/stdstreams.hh>
+#include <dune/common/visibility.hh>
+
+namespace Dune
+{
+ /**
+ * @file
+ * @brief Helpers for dealing with MPI.
+ *
+ * @ingroup ParallelCommunication
+ *
+ * Basically there are two helpers available:
+ * <dl>
+ * <dt>FakeMPIHelper</dt>
+ * <dd>A class adhering to the interface of MPIHelper
+ * that does not need MPI at all. This can be used
+ * to create a sequential program even if MPI is
+ * used to compile it.
+ * </dd>
+ * <dt>MPIHelper</dt>
+ * <dd>A real MPI helper. When the singleton
+ * gets instantiated MPI_Init will be
+ * called and before the program exits
+ * MPI_Finalize will be called.
+ * </dd>
+ * </dl>
+ *
+ * Example of who to use these classes:
+ *
+ * A program that is parallel if compiled with MPI
+ * and sequential otherwise:
+ * \code
+ * int main(int argc, char** argv){
+ * typedef Dune::MPIHelper MPIHelper;
+ * MPIHelper::instance(argc, argv);
+ * typename MPIHelper::MPICommunicator world =
+ * MPIHelper::getCommunicator();
+ * ...
+ * \endcode
+ *
+ * If one wants to have sequential program even if the code is
+ * compiled with mpi then one simply has to exchange the typedef
+ * with \code typedef Dune::MPIHelper FakeMPIHelper; \endcode.
+ *
+ * For checking whether we really use MPI or just fake please use
+ * MPIHelper::isFake (this is also possible at compile time!)
+ */
+ /**
+ * @brief A fake mpi helper.
+ *
+ * This helper can be used if no MPI is available
+ * or one wants to run sequentially even if MPI is
+ * available and used.
+ */
+ class FakeMPIHelper
+ {
+ public:
+ enum {
+ /**
+ * @brief Are we fake (i.e. pretend to have MPI support but are compiled
+ * without.)
+ */
+ isFake = true
+ };
+
+ /**
+ * @brief The type of the mpi communicator.
+ */
+ typedef No_Comm MPICommunicator;
+
+ /** \brief get the default communicator
+ *
+ * Return a communicator to exchange data with all processes
+ *
+ * \returns a fake communicator
+ */
+ DUNE_EXPORT static MPICommunicator getCommunicator ()
+ {
+ static MPICommunicator comm;
+ return comm;
+ }
+
+ /** \brief get a local communicator
+ *
+ * Returns a communicator to communicate with the local process only
+ *
+ * \returns a fake communicator
+ */
+ static MPICommunicator getLocalCommunicator ()
+ {
+ return getCommunicator();
+ }
+
+
+
+ static CollectiveCommunication<MPICommunicator>
+ getCollectiveCommunication()
+ {
+ return CollectiveCommunication<MPICommunicator>(getCommunicator());
+ }
+
+ /**
+ * @brief Get the singleton instance of the helper.
+ *
+ * This method has to be called with the same arguments
+ * that the main method of the program was called:
+ * \code
+ * int main(int argc, char** argv){
+ * MPIHelper::instance(argc, argv);
+ * // program code comes here
+ * ...
+ * }
+ * \endcode
+ * @param argc The number of arguments provided to main.
+ * @param argv The arguments provided to main.
+ */
+ DUNE_EXPORT static FakeMPIHelper& instance(int argc, char** argv)
+ {
+ (void)argc; (void)argv;
+ // create singleton instance
+ static FakeMPIHelper singleton;
+ return singleton;
+ }
+
+ /**
+ * @brief return rank of process, i.e. zero
+ */
+ int rank () const { return 0; }
+ /**
+ * @brief return rank of process, i.e. one
+ */
+ int size () const { return 1; }
+
+ private:
+ FakeMPIHelper() {}
+ FakeMPIHelper(const FakeMPIHelper&);
+ FakeMPIHelper& operator=(const FakeMPIHelper);
+ };
+
+#if HAVE_MPI
+ /**
+ * @brief A real mpi helper.
+ * @ingroup ParallelCommunication
+ *
+ * This helper should be used for parallel programs.
+ */
+ class MPIHelper
+ {
+ public:
+ enum {
+ /**
+ * @brief Are we fake (i. e. pretend to have MPI support but are compiled
+ * without.
+ */
+ isFake = false
+ };
+
+ /**
+ * @brief The type of the mpi communicator.
+ */
+ typedef MPI_Comm MPICommunicator;
+
+ /** \brief get the default communicator
+ *
+ * Return a communicator to exchange data with all processes
+ *
+ * \returns MPI_COMM_WORLD
+ */
+ static MPICommunicator getCommunicator ()
+ {
+ return MPI_COMM_WORLD;
+ }
+
+ /** \brief get a local communicator
+ *
+ * Returns a communicator to exchange data with the local process only
+ *
+ * \returns MPI_COMM_SELF
+ */
+ static MPICommunicator getLocalCommunicator ()
+ {
+ return MPI_COMM_SELF;
+ }
+
+ static CollectiveCommunication<MPICommunicator>
+ getCollectiveCommunication()
+ {
+ return CollectiveCommunication<MPICommunicator>(getCommunicator());
+ }
+ /**
+ * @brief Get the singleton instance of the helper.
+ *
+ * This method has to be called with the same arguments
+ * that the main method of the program was called:
+ * \code
+ * int main(int argc, char** argv){
+ * MPIHelper::instance(argc, argv);
+ * // program code comes here
+ * ...
+ * }
+ * \endcode
+ * @param argc The number of arguments provided to main.
+ * @param argv The arguments provided to main.
+ */
+ DUNE_EXPORT static MPIHelper& instance(int& argc, char**& argv)
+ {
+ // create singleton instance
+ static MPIHelper singleton (argc, argv);
+ return singleton;
+ }
+
+ /**
+ * @brief return rank of process
+ */
+ int rank () const { return rank_; }
+ /**
+ * @brief return number of processes
+ */
+ int size () const { return size_; }
+
+ private:
+ int rank_;
+ int size_;
+ void prevent_warning(int){}
+
+ //! \brief calls MPI_Init with argc and argv as parameters
+ MPIHelper(int& argc, char**& argv)
+ {
+#if MPI_2
+ int wasInitialized = -1;
+ MPI_Initialized( &wasInitialized );
+ if(!wasInitialized)
+#endif
+ {
+ rank_ = -1;
+ size_ = -1;
+ static int is_initialized = MPI_Init(&argc, &argv);
+ prevent_warning(is_initialized);
+ }
+
+ MPI_Comm_rank(MPI_COMM_WORLD,&rank_);
+ MPI_Comm_size(MPI_COMM_WORLD,&size_);
+
+ assert( rank_ >= 0 );
+ assert( size_ >= 1 );
+
+ dverb << "Called MPI_Init on p=" << rank_ << "!" << std::endl;
+ }
+ //! \brief calls MPI_Finalize
+ ~MPIHelper()
+ {
+#ifdef MPI_2
+ int wasFinalized = -1;
+ MPI_Finalized( &wasFinalized );
+ if(!wasFinalized) {
+#endif
+ MPI_Finalize();
+ dverb << "Called MPI_Finalize on p=" << rank_ << "!" <<std::endl;
+#ifdef MPI_2
+ }
+
+#endif
+ }
+ MPIHelper(const MPIHelper&);
+ MPIHelper& operator=(const MPIHelper);
+ };
+#else
+ // We do not have MPI therefore FakeMPIHelper
+ // is the MPIHelper
+ /**
+ * @brief If no MPI is available FakeMPIHelper becomes the MPIHelper
+ * @ingroup ParallelCommunication
+ */
+ typedef FakeMPIHelper MPIHelper;
+
+#endif
+
+} // end namespace Dune
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id: mpitraits.hh 1083 2009-09-28 17:13:20Z mblatt $
+#ifndef DUNE_MPITRAITS_HH
+#define DUNE_MPITRAITS_HH
+
+#if HAVE_MPI
+#include <mpi.h>
+#endif
+
+#include <utility>
+
+namespace Dune
+{
+ /** @addtogroup ParallelCommunication
+ *
+ * @{
+ */
+ /**
+ * @file
+ * @brief Traits classes for mapping types onto MPI_Datatype.
+ * @author Markus Blatt
+ */
+
+#if HAVE_MPI
+ /**
+ * @brief A traits class describing the mapping of types onto MPI_Datatypes.
+ *
+ * Specializations exist for the default types.
+ * Specializations should provide a static method
+ * \code
+ * static MPI_Datatype getType();
+ * \endcode
+ */
+ template<typename T>
+ struct MPITraits
+ {
+ private:
+ MPITraits(){}
+ MPITraits(const MPITraits&){}
+ static MPI_Datatype datatype;
+ static MPI_Datatype vectortype;
+ public:
+ static inline MPI_Datatype getType()
+ {
+ if(datatype==MPI_DATATYPE_NULL) {
+ MPI_Type_contiguous(sizeof(T),MPI_BYTE,&datatype);
+ MPI_Type_commit(&datatype);
+ }
+ return datatype;
+ }
+
+ };
+ template<class T>
+ MPI_Datatype MPITraits<T>::datatype = MPI_DATATYPE_NULL;
+
+#ifndef DOXYGEN
+#if HAVE_MPI
+
+ // A Macro for defining traits for the primitive data types
+#define ComposeMPITraits(p,m) \
+ template<> \
+ struct MPITraits<p>{ \
+ static inline MPI_Datatype getType(){ \
+ return m; \
+ } \
+ }
+
+ ComposeMPITraits(char, MPI_CHAR);
+ ComposeMPITraits(unsigned char,MPI_UNSIGNED_CHAR);
+ ComposeMPITraits(short,MPI_SHORT);
+ ComposeMPITraits(unsigned short,MPI_UNSIGNED_SHORT);
+ ComposeMPITraits(int,MPI_INT);
+ ComposeMPITraits(unsigned int,MPI_UNSIGNED);
+ ComposeMPITraits(long,MPI_LONG);
+ ComposeMPITraits(unsigned long,MPI_UNSIGNED_LONG);
+ ComposeMPITraits(float,MPI_FLOAT);
+ ComposeMPITraits(double,MPI_DOUBLE);
+ ComposeMPITraits(long double,MPI_LONG_DOUBLE);
+
+
+#undef ComposeMPITraits
+
+ template<class K, int n> class FieldVector;
+
+ template<class K, int n>
+ struct MPITraits<FieldVector<K,n> >
+ {
+ static MPI_Datatype datatype;
+ static MPI_Datatype vectortype;
+
+ static inline MPI_Datatype getType()
+ {
+ if(datatype==MPI_DATATYPE_NULL) {
+ MPI_Type_contiguous(n, MPITraits<K>::getType(), &vectortype);
+ MPI_Type_commit(&vectortype);
+ FieldVector<K,n> fvector;
+ MPI_Aint base;
+ MPI_Aint displ;
+ MPI_Address(&fvector, &base);
+ MPI_Address(&(fvector[0]), &displ);
+ displ -= base;
+ int length[1]={1};
+
+ MPI_Type_struct(1, length, &displ, &vectortype, &datatype);
+ MPI_Type_commit(&datatype);
+ }
+ return datatype;
+ }
+
+ };
+
+ template<class K, int n>
+ MPI_Datatype MPITraits<FieldVector<K,n> >::datatype = MPI_DATATYPE_NULL;
+ template<class K, int n>
+ MPI_Datatype MPITraits<FieldVector<K,n> >::vectortype = {MPI_DATATYPE_NULL};
+
+
+ template<int k>
+ class bigunsignedint;
+
+ template<int k>
+ struct MPITraits<bigunsignedint<k> >
+ {
+ static MPI_Datatype datatype;
+ static MPI_Datatype vectortype;
+
+ static inline MPI_Datatype getType()
+ {
+ if(datatype==MPI_DATATYPE_NULL) {
+ MPI_Type_contiguous(bigunsignedint<k>::n, MPITraits<unsigned short>::getType(),
+ &vectortype);
+ //MPI_Type_commit(&vectortype);
+ bigunsignedint<k> data;
+ MPI_Aint base;
+ MPI_Aint displ;
+ MPI_Address(&data, &base);
+ MPI_Address(&(data.digit), &displ);
+ displ -= base;
+ int length[1]={1};
+ MPI_Type_struct(1, length, &displ, &vectortype, &datatype);
+ MPI_Type_commit(&datatype);
+ }
+ return datatype;
+ }
+ };
+}
+
+namespace Dune
+{
+ template<int k>
+ MPI_Datatype MPITraits<bigunsignedint<k> >::datatype = MPI_DATATYPE_NULL;
+ template<int k>
+ MPI_Datatype MPITraits<bigunsignedint<k> >::vectortype = MPI_DATATYPE_NULL;
+
+ template<typename T1, typename T2>
+ struct MPITraits<std::pair<T1,T2 > >
+ {
+ public:
+ inline static MPI_Datatype getType();
+ private:
+ static MPI_Datatype type;
+ };
+ template<typename T1, typename T2>
+ MPI_Datatype MPITraits<std::pair<T1,T2> >::getType()
+ {
+ if(type==MPI_DATATYPE_NULL) {
+ int length[4];
+ MPI_Aint disp[4];
+ MPI_Datatype types[4] = {MPI_LB, MPITraits<T1>::getType(),
+ MPITraits<T2>::getType(), MPI_UB};
+ std::pair<T1,T2> rep[2];
+ length[0]=length[1]=length[2]=length[3]=1;
+ MPI_Address(rep, disp); // lower bound of the datatype
+ MPI_Address(&(rep[0].first), disp+1);
+ MPI_Address(&(rep[0].second), disp+2);
+ MPI_Address(rep+1, disp+3); // upper bound of the datatype
+ for(int i=3; i >= 0; --i)
+ disp[i] -= disp[0];
+ MPI_Type_struct(4, length, disp, types, &type);
+ MPI_Type_commit(&type);
+ }
+ return type;
+ }
+
+ template<typename T1, typename T2>
+ MPI_Datatype MPITraits<std::pair<T1,T2> >::type=MPI_DATATYPE_NULL;
+#endif
+#endif
+#endif
+ /** @} */
+}
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+
+#ifndef DUNE_PLOCALINDEX_HH
+#define DUNE_PLOCALINDEX_HH
+
+#include "localindex.hh"
+#include "indexset.hh"
+#include "mpitraits.hh"
+
+#include <iostream>
+
+namespace Dune
+{
+
+
+ /** @addtogroup Common_Parallel
+ *
+ * @{
+ */
+ /**
+ * @file
+ * @brief Provides classes for use as the local index in ParallelIndexSet for distributed computing.
+ * @author Markus Blatt
+ */
+
+ template<class T> class ParallelLocalIndex;
+
+ /**
+ * @brief Print the local index to a stream.
+ * @param os The output stream to print to.
+ * @param index The index to print.
+ */
+ template<class T>
+ std::ostream& operator<<(std::ostream& os, const ParallelLocalIndex<T>& index)
+ {
+ os<<"{local="<<index.localIndex_<<", attr="<<T(index.attribute_)<<", public="
+ <<(index.public_ ? true : false)<<"}";
+ return os;
+ }
+
+ /**
+ * @brief An index present on the local process with an additional attribute flag.
+ */
+ template<typename T>
+ class ParallelLocalIndex
+ {
+#if HAVE_MPI
+ // friend declaration needed for MPITraits
+ friend struct MPITraits<ParallelLocalIndex<T> >;
+#endif
+ friend std::ostream& operator<<<>(std::ostream& os, const ParallelLocalIndex<T>& index);
+
+ public:
+ /**
+ * @brief The type of the attributes.
+ * Normally this will be an enumeration like
+ * <pre>
+ * enum Attributes{owner, border, overlap};
+ * </pre>
+ */
+ typedef T Attribute;
+ /**
+ * @brief Constructor.
+ *
+ * The local index will be initialized to 0.
+ * @param attribute The attribute of the index.
+ * @param isPublic True if the index might also be
+ * known to other processes.
+ */
+ ParallelLocalIndex(const Attribute& attribute, bool isPublic);
+
+ /**
+ * @brief Constructor.
+ *
+ * @param localIndex The local index.
+ * @param attribute The attribute of the index.
+ * @param isPublic True if the index might also be
+ * known to other processes.
+ */
+ ParallelLocalIndex(size_t localIndex, const Attribute& attribute, bool isPublic=true);
+ /**
+ * @brief Parameterless constructor.
+ *
+ * Needed for use in container classes.
+ */
+ ParallelLocalIndex();
+
+#if 0
+ /**
+ * @brief Constructor.
+ * @param globalIndex The global index.
+ * @param attribute The attribute of the index.
+ * @param local The local index.
+ * @param isPublic True if the index might also be
+ * known to other processes.
+ *
+ */
+ ParallelLocalIndex(const Attribute& attribute, size_t local, bool isPublic);
+#endif
+
+ /**
+ * @brief Get the attribute of the index.
+ * @return The associated attribute.
+ */
+ inline const Attribute attribute() const;
+
+ /**
+ * @brief Set the attribute of the index.
+ * @param attribute The associated attribute.
+ */
+ inline void setAttribute(const Attribute& attribute);
+
+ /**
+ * @brief get the local index.
+ * @return The local index.
+ */
+ inline size_t local() const;
+
+ /**
+ * @brief Convert to the local index represented by an int.
+ */
+ inline operator size_t() const;
+
+ /**
+ * @brief Assign a new local index.
+ *
+ * @param index The new local index.
+ */
+ inline ParallelLocalIndex<Attribute>& operator=(size_t index);
+
+ /**
+ * @brief Check whether the index might also be known other processes.
+ * @return True if the index might be known to other processors.
+ */
+ inline bool isPublic() const;
+
+ /**
+ * @brief Get the state.
+ * @return The state.
+ */
+ inline LocalIndexState state() const;
+
+ /**
+ * @brief Set the state.
+ * @param state The state to set.
+ */
+ inline void setState(const LocalIndexState& state);
+
+ private:
+ /** @brief The local index. */
+ size_t localIndex_;
+
+ /** @brief An attribute for the index. */
+ char attribute_;
+
+ /** @brief True if the index is also known to other processors. */
+ char public_;
+
+ /**
+ * @brief The state of the index.
+ *
+ * Has to be one of LocalIndexState!
+ * @see LocalIndexState.
+ */
+ char state_;
+
+ };
+
+ template<typename T>
+ bool operator==(const ParallelLocalIndex<T>& p1,
+ const ParallelLocalIndex<T>& p2)
+ {
+ if(p1.local()!=p2.local())
+ return false;
+ if(p1.attribute()!=p2.attribute())
+ return false;
+ if(p1.isPublic()!=p2.isPublic())
+ return false;
+ return true;
+ }
+ template<typename T>
+ bool operator!=(const ParallelLocalIndex<T>& p1,
+ const ParallelLocalIndex<T>& p2)
+ {
+ return !(p1==p2);
+ }
+
+
+ template<typename T>
+ struct LocalIndexComparator<ParallelLocalIndex<T> >
+ {
+ static bool compare(const ParallelLocalIndex<T>& t1,
+ const ParallelLocalIndex<T>& t2){
+ return t1.attribute()<t2.attribute();
+ }
+ };
+
+
+#if HAVE_MPI
+
+ //! \todo Please doc me!
+ template<typename T>
+ class MPITraits<ParallelLocalIndex<T> >
+ {
+ public:
+ static MPI_Datatype getType();
+ private:
+ static MPI_Datatype type;
+
+ };
+
+#endif
+
+ template<class T>
+ ParallelLocalIndex<T>::ParallelLocalIndex(const T& attribute, bool isPublic)
+ : localIndex_(0), attribute_(static_cast<char>(attribute)),
+ public_(static_cast<char>(isPublic)), state_(static_cast<char>(VALID))
+ {}
+
+
+ template<class T>
+ ParallelLocalIndex<T>::ParallelLocalIndex(size_t local, const T& attribute, bool isPublic)
+ : localIndex_(local), attribute_(static_cast<char>(attribute)),
+ public_(static_cast<char>(isPublic)), state_(static_cast<char>(VALID))
+ {}
+
+ template<class T>
+ ParallelLocalIndex<T>::ParallelLocalIndex()
+ : localIndex_(0), attribute_(), public_(static_cast<char>(false)),
+ state_(static_cast<char>(VALID))
+ {}
+
+ template<class T>
+ inline const T ParallelLocalIndex<T>::attribute() const
+ {
+ return T(attribute_);
+ }
+
+ template<class T>
+ inline void
+ ParallelLocalIndex<T>::setAttribute(const Attribute& attribute)
+ {
+ attribute_ = attribute;
+ }
+
+ template<class T>
+ inline size_t ParallelLocalIndex<T>::local() const
+ {
+ return localIndex_;
+ }
+
+ template<class T>
+ inline ParallelLocalIndex<T>::operator size_t() const
+ {
+ return localIndex_;
+ }
+
+ template<class T>
+ inline ParallelLocalIndex<T>&
+ ParallelLocalIndex<T>::operator=(size_t index)
+ {
+ localIndex_=index;
+ return *this;
+ }
+
+ template<class T>
+ inline bool ParallelLocalIndex<T>::isPublic() const
+ {
+ return static_cast<bool>(public_);
+ }
+
+ template<class T>
+ inline LocalIndexState ParallelLocalIndex<T>::state() const
+ {
+ return LocalIndexState(state_);
+ }
+
+ template<class T>
+ inline void ParallelLocalIndex<T>::setState(const LocalIndexState& state)
+ {
+ state_=static_cast<char>(state);
+ }
+
+#if HAVE_MPI
+
+ template<typename T>
+ MPI_Datatype MPITraits<ParallelLocalIndex<T> >::getType()
+ {
+
+ if(type==MPI_DATATYPE_NULL) {
+ int length[3];
+ MPI_Aint disp[3];
+ MPI_Datatype types[3] = {MPI_LB, MPITraits<char>::getType(), MPI_UB};
+ ParallelLocalIndex<T> rep[2];
+ length[0]=length[1]=length[2]=1;
+ MPI_Address(rep, disp); // lower bound of the datatype
+ MPI_Address(&(rep[0].attribute_), disp+1);
+ MPI_Address(rep+1, disp+2); // upper bound of the datatype
+ for(int i=2; i >= 0; --i)
+ disp[i] -= disp[0];
+ MPI_Type_struct(3, length, disp, types, &type);
+ MPI_Type_commit(&type);
+ }
+ return type;
+ }
+
+ template<typename T>
+ MPI_Datatype MPITraits<ParallelLocalIndex<T> >::type = MPI_DATATYPE_NULL;
+
+#endif
+
+
+ /** @} */
+} // namespace Dune
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+#ifndef DUNE_REMOTEINDICES_HH
+#define DUNE_REMOTEINDICES_HH
+
+#include "indexset.hh"
+#include "plocalindex.hh"
+#include <dune/common/exceptions.hh>
+#include <dune/common/poolallocator.hh>
+#include <dune/common/sllist.hh>
+#include <dune/common/static_assert.hh>
+#include <dune/common/stdstreams.hh>
+#include <map>
+#include <set>
+#include <utility>
+#include <iostream>
+#include <algorithm>
+#include <iterator>
+#if HAVE_MPI
+#include "mpitraits.hh"
+#include <mpi.h>
+
+namespace Dune {
+ /** @addtogroup Common_Parallel
+ *
+ * @{
+ */
+ /**
+ * @file
+ * @brief Classes describing a distributed indexset
+ * @author Markus Blatt
+ */
+
+ //! \todo Please doc me!
+ template<typename TG, typename TA>
+ class MPITraits<IndexPair<TG,ParallelLocalIndex<TA> > >
+ {
+ public:
+ inline static MPI_Datatype getType();
+ private:
+ static MPI_Datatype type;
+ };
+
+
+ template<typename T, typename A>
+ class RemoteIndices;
+
+ template<typename T1, typename T2>
+ class RemoteIndex;
+
+ template<typename T>
+ class IndicesSyncer;
+
+ template<typename T1, typename T2>
+ std::ostream& operator<<(std::ostream& os, const RemoteIndex<T1,T2>& index);
+
+
+ template<typename T, typename A, bool mode>
+ class RemoteIndexListModifier;
+
+
+ /**
+ * @brief Information about an index residing on another processor.
+ */
+ template<typename T1, typename T2>
+ class RemoteIndex
+ {
+ template<typename T>
+ friend class IndicesSyncer;
+
+ template<typename T, typename A, typename A1>
+ friend void repairLocalIndexPointers(std::map<int,SLList<std::pair<typename T::GlobalIndex, typename T::LocalIndex::Attribute>,A> >&,
+ RemoteIndices<T,A1>&,
+ const T&);
+
+ template<typename T, typename A, bool mode>
+ friend class RemoteIndexListModifier;
+
+ public:
+ /**
+ * @brief the type of the global index.
+ * This type has to provide at least a operator< for sorting.
+ */
+ typedef T1 GlobalIndex;
+ /**
+ * @brief The type of the attributes.
+ * Normally this will be an enumeration like
+ * \code
+ * enum Attributes{owner, border, overlap}
+ * \endcode
+ * e.g. OwnerOverlapCopyAttributes.
+ */
+ typedef T2 Attribute;
+
+ /**
+ * @brief The type of the index pair.
+ */
+ typedef IndexPair<GlobalIndex,ParallelLocalIndex<Attribute> >
+ PairType;
+
+ /**
+ * @brief Get the attribute of the index on the remote process.
+ * @return The remote attribute.
+ */
+ const Attribute attribute() const;
+
+ /**
+ * @brief Get the corresponding local index pair.
+ * @return The corresponding local index pair.
+ */
+
+ const PairType& localIndexPair() const;
+
+ /**
+ * @brief Parameterless Constructor.
+ */
+ RemoteIndex();
+
+
+ /**
+ * @brief Constructor.
+ * @param attribute The attribute of the index on the remote processor.
+ * @param local The corresponding local index.
+ */
+ RemoteIndex(const T2& attribute,
+ const PairType* local);
+
+
+ /**
+ * @brief Constructor.
+ * Private as it should only be called from within Indexset.
+ * @param attribute The attribute of the index on the remote processor.
+ */
+ RemoteIndex(const T2& attribute);
+
+ bool operator==(const RemoteIndex& ri) const;
+
+ bool operator!=(const RemoteIndex& ri) const;
+ private:
+ /** @brief The corresponding local index for this process. */
+ const PairType* localIndex_;
+
+ /** @brief The attribute of the index on the other process. */
+ char attribute_;
+ };
+
+ template<class T, class A>
+ std::ostream& operator<<(std::ostream& os, const RemoteIndices<T,A>& indices);
+
+ class InterfaceBuilder;
+
+ template<class T, class A>
+ class CollectiveIterator;
+
+ template<class T>
+ class IndicesSyncer;
+
+ // forward declaration needed for friend declaration.
+ template<typename T1, typename T2>
+ class OwnerOverlapCopyCommunication;
+
+
+ /**
+ * @brief The indices present on remote processes.
+ *
+ * To set up communication between the set of processes active in
+ * the communication every process needs to know which
+ * indices are also known to other processes and which attributes
+ * are attached to them on the remote side.
+ *
+ * This information is managed by this class. The information can either
+ * be computed automatically calling rebuild (which requires information
+ * to be sent in a ring) or set up by hand using the
+ * RemoteIndexListModifiers returned by function getModifier(int).
+ *
+ * @tparam T The type of the underlying index set.
+ * @tparam A The type of the allocator to use.
+ */
+ template<class T, class A=std::allocator<RemoteIndex<typename T::GlobalIndex,
+ typename T::LocalIndex::Attribute> > >
+ class RemoteIndices
+ {
+ friend class InterfaceBuilder;
+ friend class IndicesSyncer<T>;
+ template<typename T1, typename A2, typename A1>
+ friend void repairLocalIndexPointers(std::map<int,SLList<std::pair<typename T1::GlobalIndex, typename T1::LocalIndex::Attribute>,A2> >&,
+ RemoteIndices<T1,A1>&,
+ const T1&);
+
+ template<class G, class T1, class T2>
+ friend void fillIndexSetHoles(const G& graph, Dune::OwnerOverlapCopyCommunication<T1,T2>& oocomm);
+ friend std::ostream& operator<<<>(std::ostream&, const RemoteIndices<T>&);
+
+ public:
+
+ /**
+ * @brief Type of the index set we use, e.g. ParallelLocalIndexSet.
+ */
+ typedef T ParallelIndexSet;
+
+ /**
+ * @brief The type of the collective iterator over all remote indices. */
+ typedef CollectiveIterator<T,A> CollectiveIteratorT;
+
+ /**
+ * @brief The type of the global index.
+ */
+ typedef typename ParallelIndexSet::GlobalIndex GlobalIndex;
+
+
+ /**
+ * @brief The type of the local index.
+ */
+ typedef typename ParallelIndexSet::LocalIndex LocalIndex;
+
+ /**
+ * @brief The type of the attribute.
+ */
+ typedef typename LocalIndex::Attribute Attribute;
+
+ /**
+ * @brief Type of the remote indices we manage.
+ */
+ typedef Dune::RemoteIndex<GlobalIndex,Attribute> RemoteIndex;
+
+
+ /**
+ * @brief The type of the allocator for the remote index list.
+ */
+ typedef typename A::template rebind<RemoteIndex>::other Allocator;
+
+ /** @brief The type of the remote index list. */
+ typedef Dune::SLList<RemoteIndex,Allocator>
+ RemoteIndexList;
+
+ /** @brief The type of the map from rank to remote index list. */
+ typedef std::map<int, std::pair<RemoteIndexList*,RemoteIndexList*> >
+ RemoteIndexMap;
+
+ typedef typename RemoteIndexMap::const_iterator const_iterator;
+
+ /**
+ * @brief Constructor.
+ * @param comm The communicator to use.
+ * @param source The indexset which represents the global to
+ * local mapping at the source of the communication
+ * @param destination The indexset to which the communication
+ * which represents the global to
+ * local mapping at the destination of the communication.
+ * May be the same as the source indexset.
+ * @param neighbours Optional: The neighbours the process shares indices with.
+ * If this parameter is omitted a ring communication with all indices will take
+ * place to calculate this information which is O(P).
+ * @param includeSelf If true, sending from indices of the processor to other
+ * indices on the same processor is enabled even if the same indexset is used
+ * on both the
+ * sending and receiving side.
+ */
+ inline RemoteIndices(const ParallelIndexSet& source, const ParallelIndexSet& destination,
+ const MPI_Comm& comm, const std::vector<int>& neighbours=std::vector<int>(), bool includeSelf=false);
+
+ RemoteIndices();
+
+ /**
+ * @brief Tell whether sending from indices of the processor to other
+ * indices on the same processor is enabled even if the same indexset is
+ * used on both the sending and receiving side.
+ *
+ * @param includeSelf If true it is enabled.
+ */
+ void setIncludeSelf(bool includeSelf);
+
+ /**
+ * @brief Set the index sets and communicator we work with.
+ *
+ * @warning All remote indices already setup will be deleted!
+ *
+ * @param comm The communicator to use.
+ * @param source The indexset which represents the global to
+ * local mapping at the source of the communication
+ * @param destination The indexset to which the communication
+ * which represents the global to
+ * local mapping at the destination of the communication.
+ * May be the same as the source indexset.
+ * @param neighbours Optional: The neighbours the process shares indices with.
+ * If this parameter is omitted a ring communication with all indices will take
+ * place to calculate this information which is O(P).
+ */
+ void setIndexSets(const ParallelIndexSet& source, const ParallelIndexSet& destination,
+ const MPI_Comm& comm, const std::vector<int>& neighbours=std::vector<int>());
+
+ template<typename C>
+ void setNeighbours(const C& neighbours)
+ {
+ neighbourIds.clear();
+ neighbourIds.insert(neighbours.begin(), neighbours.end());
+
+ }
+
+ const std::set<int>& getNeighbours() const
+ {
+ return neighbourIds;
+ }
+
+ /**
+ * @brief Destructor.
+ */
+ ~RemoteIndices();
+
+ /**
+ * @brief Rebuilds the set of remote indices.
+ *
+ * This has to be called whenever the underlying index sets
+ * change.
+ *
+ * If the template parameter ignorePublic is true all indices will be treated
+ * as public.
+ */
+ template<bool ignorePublic>
+ void rebuild();
+
+ bool operator==(const RemoteIndices& ri);
+
+ /**
+ * @brief Checks whether the remote indices are synced with
+ * the indexsets.
+ *
+ * If they are not synced the remote indices need to be rebuild.
+ * @return True if they are synced.
+ */
+ inline bool isSynced() const;
+
+ /**
+ * @brief Get the mpi communicator used.
+ */
+ inline MPI_Comm communicator() const;
+
+ /**
+ * @brief Get a modifier for a remote index list.
+ *
+ * Sometimes the user knows in advance which indices will be present
+ * on other processors, too. Then he can set them up using this modifier.
+ *
+ * @warning Use with care. If the remote index list is inconsistent
+ * after the modification the communication might result in a dead lock!
+ *
+ * @tparam mode If true the index set corresponding to the remote indices might get modified.
+ * Therefore the internal pointers to the indices need to be repaired.
+ * @tparam send If true the remote index information at the sending side will
+ * be modified, if false the receiving side.
+ */
+ template<bool mode, bool send>
+ inline RemoteIndexListModifier<T,A,mode> getModifier(int process);
+
+ /**
+ * @brief Find an iterator over the remote index lists of a specific process.
+ * @param proc The identifier of the process.
+ * @return The iterator the remote index lists postioned at the process.
+ * If theres is no list for this process, the end iterator is returned.
+ */
+ inline const_iterator find(int proc) const;
+
+ /**
+ * @brief Get an iterator over all remote index lists.
+ * @return The iterator over all remote index lists postioned at the first process.
+ */
+ inline const_iterator begin() const;
+
+ /**
+ * @brief Get an iterator over all remote index lists.
+ * @return The iterator over all remote index lists postioned at the end.
+ */
+ inline const_iterator end() const;
+
+ /**
+ * @brief Get an iterator for colletively iterating over the remote indices of all remote processes.
+ */
+ template<bool send>
+ inline CollectiveIteratorT iterator() const;
+
+ /**
+ * @brief Free the index lists.
+ */
+ inline void free();
+
+ /**
+ * @brief Get the number of processors we share indices with.
+ * @return The number of neighbours.
+ */
+ inline int neighbours() const;
+
+ /** @brief Get the index set at the source. */
+ inline const ParallelIndexSet& sourceIndexSet() const;
+
+ /** @brief Get the index set at destination. */
+ inline const ParallelIndexSet& destinationIndexSet() const;
+
+ private:
+ /** copying is forbidden. */
+ RemoteIndices(const RemoteIndices&)
+ {}
+
+ /** @brief Index set used at the source of the communication. */
+ const ParallelIndexSet* source_;
+
+ /** @brief Index set used at the destination of the communication. */
+ const ParallelIndexSet* target_;
+
+ /** @brief The communicator to use.*/
+ MPI_Comm comm_;
+
+ /** @brief The neighbours we share indices with.
+ * If not empty this will speedup rebuild. */
+ std::set<int> neighbourIds;
+
+ /** @brief The communicator tag to use. */
+ const static int commTag_=333;
+
+ /**
+ * @brief The sequence number of the source index set when the remote indices
+ * where build.
+ */
+ int sourceSeqNo_;
+
+ /**
+ * @brief The sequence number of the destination index set when the remote indices
+ * where build.
+ */
+ int destSeqNo_;
+
+ /**
+ * @brief Whether the public flag was ignored during the build.
+ */
+ bool publicIgnored;
+
+ /**
+ * @brief Whether the next build will be the first build ever.
+ */
+ bool firstBuild;
+
+ /*
+ * @brief If true, sending from indices of the processor to other
+ * indices on the same processor is enabled even if the same indexset is used
+ * on both the
+ * sending and receiving side.
+ */
+ bool includeSelf;
+
+ /** @brief The index pair type. */
+ typedef IndexPair<GlobalIndex, LocalIndex>
+ PairType;
+
+ /**
+ * @brief The remote indices.
+ *
+ * The key is the process id and the values are the pair of remote
+ * index lists, the first for receiving, the second for sending.
+ */
+ RemoteIndexMap remoteIndices_;
+
+ /**
+ * @brief Build the remote mapping.
+ *
+ * If the template parameter ignorePublic is true all indices will be treated
+ * as public.
+ * @param includeSelf If true, sending from indices of the processor to other
+ * indices on the same processor is enabled even if the same indexset is used
+ * on both the
+ * sending and receiving side.
+ */
+ template<bool ignorePublic>
+ inline void buildRemote(bool includeSelf);
+
+ /**
+ * @brief Count the number of public indices in an index set.
+ * @param indexSet The index set whose indices we count.
+ * @return the number of indices marked as public.
+ */
+ inline int noPublic(const ParallelIndexSet& indexSet);
+
+ /**
+ * @brief Pack the indices to send if source_ and target_ are the same.
+ *
+ * If the template parameter ignorePublic is true all indices will be treated
+ * as public.
+ * @param myPairs Array to store references to the public indices in.
+ * @param p_out The output buffer to pack the entries to.
+ * @param type The mpi datatype for the pairs.
+ * @param bufferSize The size of the output buffer p_out.
+ * @param position The position to start packing.
+ */
+ template<bool ignorePublic>
+ inline void packEntries(PairType** myPairs, const ParallelIndexSet& indexSet,
+ char* p_out, MPI_Datatype type, int bufferSize,
+ int* position, int n);
+
+ /**
+ * @brief unpacks the received indices and builds the remote index list.
+ *
+ * @param remote The list to add the indices to.
+ * @param remoteEntries The number of remote entries to unpack.
+ * @param local The local indices to check wether we know the remote
+ * indices.
+ * @param localEntries The number of local indices.
+ * @param type The mpi data type for unpacking.
+ * @param p_in The input buffer to unpack from.
+ * @param postion The position in the buffer to start unpacking from.
+ * @param bufferSize The size of the input buffer.
+ */
+ inline void unpackIndices(RemoteIndexList& remote, int remoteEntries,
+ PairType** local, int localEntries, char* p_in,
+ MPI_Datatype type, int* positon, int bufferSize,
+ bool fromOurself);
+
+ inline void unpackIndices(RemoteIndexList& send, RemoteIndexList& receive,
+ int remoteEntries, PairType** localSource,
+ int localSourceEntries, PairType** localDest,
+ int localDestEntries, char* p_in,
+ MPI_Datatype type, int* position, int bufferSize);
+
+ void unpackCreateRemote(char* p_in, PairType** sourcePairs, PairType** DestPairs,
+ int remoteProc, int sourcePublish, int destPublish,
+ int bufferSize, bool sendTwo, bool fromOurSelf=false);
+ };
+
+ /** @} */
+
+ /**
+ * @brief Modifier for adding and/or deleting remote indices from
+ * the remote index list.
+ *
+ * In some cases all the information about the indices also present
+ * on remote process might already be known. In this case this
+ * information can be provided to the RemoteIndices via this modifier.
+ * This prevents the global communication needed by a call to
+ * RemoteIndices::rebuild.
+ *
+ * In some cases it might advisable to run IndicesSyncer::sync afterwards.
+ *
+ * @warning Use with care. If the indices are not consistent afterwards
+ * communication attempts might deadlock!
+ */
+ template<class T, class A, bool mode>
+ class RemoteIndexListModifier
+ {
+
+ template<typename T1, typename A1>
+ friend class RemoteIndices;
+
+ public:
+ class InvalidPosition : public RangeError
+ {};
+
+ enum {
+ /**
+ * @brief If true the index set corresponding to the
+ * remote indices might get modified.
+ *
+ * If for example new indices are added to an index set
+ * all pointers of the remote indices to the local indices
+ * become invalid after ParallelIndexSet::endResize() was called.
+ */
+ MODIFYINDEXSET=mode
+ };
+
+ /**
+ * @brief Type of the index set we use.
+ */
+ typedef T ParallelIndexSet;
+
+ /**
+ * @brief The type of the global index.
+ */
+ typedef typename ParallelIndexSet::GlobalIndex GlobalIndex;
+
+ /**
+ * @brief The type of the local index.
+ */
+ typedef typename ParallelIndexSet::LocalIndex LocalIndex;
+
+ /**
+ * @brief The type of the attribute.
+ */
+ typedef typename LocalIndex::Attribute Attribute;
+
+ /**
+ * @brief Type of the remote indices we manage.
+ */
+ typedef Dune::RemoteIndex<GlobalIndex,Attribute> RemoteIndex;
+
+ /**
+ * @brief The type of the allocator for the remote index list.
+ */
+ typedef A Allocator;
+
+ /** @brief The type of the remote index list. */
+ typedef Dune::SLList<RemoteIndex,Allocator>
+ RemoteIndexList;
+
+ /**
+ * @brief The type of the modifying iterator of the remote index list.
+ */
+ typedef SLListModifyIterator<RemoteIndex,Allocator> ModifyIterator;
+
+ /**
+ * @brief The type of the remote index list iterator.
+ */
+ typedef typename RemoteIndexList::const_iterator ConstIterator;
+
+ /**
+ * @brief Insert an index to the list.
+ *
+ * Moves to the position where the index fits and inserts it.
+ * After the insertion only indices with an bigger global index
+ * than the inserted can be inserted.
+ *
+ * This method is only available if MODIFYINDEXSET is false.
+ *
+ * @param index The index to insert.
+ * @exception InvalidPosition Thrown if the index at the current position or
+ * the one before has bigger global index than the one to be inserted.
+ */
+ void insert(const RemoteIndex& index) throw(InvalidPosition);
+
+
+ /**
+ * @brief Insert an index to the list.
+ *
+ * Moves to the position where the index fits and inserts it.
+ * After the insertion only indices with an bigger global index
+ * than the inserted can be inserted.
+ *
+ * This method is only available if MODIFYINDEXSET is true.
+ *
+ * @param index The index to insert.
+ * @param global The global index of the remote index.
+ * @exception InvalidPosition Thrown if the index at the current position or
+ * the one before has bigger global index than the one to be inserted.
+ */
+ void insert(const RemoteIndex& index, const GlobalIndex& global) throw(InvalidPosition);
+
+ /**
+ * @brief Remove a remote index.
+ * @param global The global index corresponding to the remote index.
+ * @return True If there was a corresponding remote index.
+ * @exception InvalidPostion If there was an insertion or deletion of
+ * a remote index corresponding to a bigger global index before.
+ */
+ bool remove(const GlobalIndex& global) throw(InvalidPosition);
+
+ /**
+ * @brief Repair the pointers to the local index pairs.
+ *
+ * Due to adding new indices or/and deleting indices in the
+ * index set all pointers to the local index pair might become
+ * invalid during ParallelIndexSet::endResize().
+ * This method repairs them.
+ *
+ * @exception InvalidIndexSetState Thrown if the underlying
+ * index set is not in ParallelIndexSetState::GROUND mode (only when
+ * compiled with DUNE_ISTL_WITH_CHECKING!).
+ */
+ void repairLocalIndexPointers() throw(InvalidIndexSetState);
+
+
+ RemoteIndexListModifier(const RemoteIndexListModifier&);
+
+ /**
+ * @brief Default constructor.
+ * @warning Object is not usable!
+ */
+ RemoteIndexListModifier()
+ : glist_()
+ {}
+
+ private:
+
+ /**
+ * @brief Create a modifier for a remote index list.
+ * @param indexSet The set of indices the process knows.
+ * @param rList The list of remote indices to modify.
+ */
+ RemoteIndexListModifier(const ParallelIndexSet& indexSet,
+ RemoteIndexList& rList);
+
+ typedef SLList<GlobalIndex,Allocator> GlobalList;
+ typedef typename GlobalList::ModifyIterator GlobalModifyIterator;
+ RemoteIndexList* rList_;
+ const ParallelIndexSet* indexSet_;
+ GlobalList glist_;
+ ModifyIterator iter_;
+ GlobalModifyIterator giter_;
+ ConstIterator end_;
+ bool first_;
+ GlobalIndex last_;
+ };
+
+ /**
+ * @brief A collective iterator for moving over the remote indices for
+ * all processes collectively.
+ */
+ template<class T, class A>
+ class CollectiveIterator
+ {
+
+ /**
+ * @brief Type of the index set we use.
+ */
+ typedef T ParallelIndexSet;
+
+ /**
+ * @brief The type of the global index.
+ */
+ typedef typename ParallelIndexSet::GlobalIndex GlobalIndex;
+
+ /**
+ * @brief The type of the local index.
+ */
+ typedef typename ParallelIndexSet::LocalIndex LocalIndex;
+
+ /**
+ * @brief The type of the attribute.
+ */
+ typedef typename LocalIndex::Attribute Attribute;
+
+ /** @brief The remote index type */
+ typedef Dune::RemoteIndex<GlobalIndex,Attribute> RemoteIndex;
+
+ /** @brief The allocator of the remote indices. */
+ typedef typename A::template rebind<RemoteIndex>::other Allocator;
+
+ /** @brief The type of the remote index list. */
+ typedef Dune::SLList<RemoteIndex,Allocator> RemoteIndexList;
+
+ /** @brief The of map for storing the iterators. */
+ typedef std::map<int,std::pair<typename RemoteIndexList::const_iterator,
+ const typename RemoteIndexList::const_iterator> >
+ Map;
+
+ public:
+
+ /** @brief The type of the map from rank to remote index list. */
+ typedef std::map<int, std::pair<RemoteIndexList*,RemoteIndexList*> >
+ RemoteIndexMap;
+
+ /**
+ * @brief Constructor.
+ * @param map_ The map of the remote indices.
+ * @param send True if we want iterate over the remote indices used for sending.
+ */
+ inline CollectiveIterator(const RemoteIndexMap& map_, bool send);
+
+ /**
+ * @brief Advances all underlying iterators.
+ *
+ * All iterators are advanced until they point to a remote index whose
+ * global id is bigger or equal to global.
+ * Iterators pointing to their end are removed.
+ * @param global The index we search for.
+ */
+ inline void advance(const GlobalIndex& global);
+
+ /**
+ * @brief Advances all underlying iterators.
+ *
+ * All iterators are advanced until they point to a remote index whose
+ * global id is bigger or equal to global.
+ * Iterators pointing to their end are removed.
+ * @param global The index we search for.
+ * @param attribute The attribute we search for.
+ */
+ inline void advance(const GlobalIndex& global, const Attribute& attribute);
+
+ CollectiveIterator& operator++();
+
+ /**
+ * @brief Checks whether there are still iterators in the map.
+ */
+ inline bool empty();
+
+ /**
+ * @brief Iterator over the valid underlying iterators.
+ *
+ * An iterator is valid if it points to a remote index whose
+ * global id is equal to the one currently examined.
+ */
+ class iterator
+ {
+ public:
+ typedef typename Map::iterator RealIterator;
+ typedef typename Map::iterator ConstRealIterator;
+
+
+ //! \todo Please doc me!
+ iterator(const RealIterator& iter, const ConstRealIterator& end, GlobalIndex& index)
+ : iter_(iter), end_(end), index_(index), hasAttribute(false)
+ {
+ // Move to the first valid entry
+ while(iter_!=end_ && iter_->second.first->localIndexPair().global()!=index_)
+ ++iter_;
+ }
+
+ iterator(const RealIterator& iter, const ConstRealIterator& end, GlobalIndex index,
+ Attribute attribute)
+ : iter_(iter), end_(end), index_(index), attribute_(attribute), hasAttribute(true)
+ {
+ // Move to the first valid entry or the end
+ while(iter_!=end_ && (iter_->second.first->localIndexPair().global()!=index_
+ || iter_->second.first->localIndexPair().local().attribute()!=attribute))
+ ++iter_;
+ }
+ //! \todo Please doc me!
+ iterator(const iterator& other)
+ : iter_(other.iter_), end_(other.end_), index_(other.index_)
+ { }
+
+ //! \todo Please doc me!
+ iterator& operator++()
+ {
+ ++iter_;
+ // If entry is not valid move on
+ while(iter_!=end_ && (iter_->second.first->localIndexPair().global()!=index_ ||
+ (hasAttribute &&
+ iter_->second.first->localIndexPair().local().attribute()!=attribute_)))
+ ++iter_;
+ assert(iter_==end_ ||
+ (iter_->second.first->localIndexPair().global()==index_));
+ assert(iter_==end_ || !hasAttribute ||
+ (iter_->second.first->localIndexPair().local().attribute()==attribute_));
+ return *this;
+ }
+
+ //! \todo Please doc me!
+ const RemoteIndex& operator*() const
+ {
+ return *(iter_->second.first);
+ }
+
+ //! \todo Please doc me!
+ int process() const
+ {
+ return iter_->first;
+ }
+
+ //! \todo Please doc me!
+ const RemoteIndex* operator->() const
+ {
+ return iter_->second.first.operator->();
+ }
+
+ //! \todo Please doc me!
+ bool operator==(const iterator& other)
+ {
+ return other.iter_==iter_;
+ }
+
+ //! \todo Please doc me!
+ bool operator!=(const iterator& other)
+ {
+ return other.iter_!=iter_;
+ }
+
+ private:
+ iterator();
+
+ RealIterator iter_;
+ RealIterator end_;
+ GlobalIndex index_;
+ Attribute attribute_;
+ bool hasAttribute;
+ };
+
+ iterator begin();
+
+ iterator end();
+
+ private:
+
+ Map map_;
+ GlobalIndex index_;
+ Attribute attribute_;
+ bool noattribute;
+ };
+
+ template<typename TG, typename TA>
+ MPI_Datatype MPITraits<IndexPair<TG,ParallelLocalIndex<TA> > >::getType()
+ {
+ if(type==MPI_DATATYPE_NULL) {
+ int length[4];
+ MPI_Aint disp[4];
+ MPI_Datatype types[4] = {MPI_LB, MPITraits<TG>::getType(),
+ MPITraits<ParallelLocalIndex<TA> >::getType(), MPI_UB};
+ IndexPair<TG,ParallelLocalIndex<TA> > rep[2];
+ length[0]=length[1]=length[2]=length[3]=1;
+ MPI_Address(rep, disp); // lower bound of the datatype
+ MPI_Address(&(rep[0].global_), disp+1);
+ MPI_Address(&(rep[0].local_), disp+2);
+ MPI_Address(rep+1, disp+3); // upper bound of the datatype
+ for(int i=3; i >= 0; --i)
+ disp[i] -= disp[0];
+ MPI_Type_struct(4, length, disp, types, &type);
+ MPI_Type_commit(&type);
+ }
+ return type;
+ }
+
+ template<typename TG, typename TA>
+ MPI_Datatype MPITraits<IndexPair<TG,ParallelLocalIndex<TA> > >::type=MPI_DATATYPE_NULL;
+
+ template<typename T1, typename T2>
+ RemoteIndex<T1,T2>::RemoteIndex(const T2& attribute, const PairType* local)
+ : localIndex_(local), attribute_(attribute)
+ {}
+
+ template<typename T1, typename T2>
+ RemoteIndex<T1,T2>::RemoteIndex(const T2& attribute)
+ : localIndex_(0), attribute_(attribute)
+ {}
+
+ template<typename T1, typename T2>
+ RemoteIndex<T1,T2>::RemoteIndex()
+ : localIndex_(0), attribute_()
+ {}
+ template<typename T1, typename T2>
+ inline bool RemoteIndex<T1,T2>::operator==(const RemoteIndex& ri) const
+ {
+ return localIndex_==ri.localIndex_ && attribute_==ri.attribute;
+ }
+
+ template<typename T1, typename T2>
+ inline bool RemoteIndex<T1,T2>::operator!=(const RemoteIndex& ri) const
+ {
+ return localIndex_!=ri.localIndex_ || attribute_!=ri.attribute_;
+ }
+
+ template<typename T1, typename T2>
+ inline const T2 RemoteIndex<T1,T2>::attribute() const
+ {
+ return T2(attribute_);
+ }
+
+ template<typename T1, typename T2>
+ inline const IndexPair<T1,ParallelLocalIndex<T2> >& RemoteIndex<T1,T2>::localIndexPair() const
+ {
+ return *localIndex_;
+ }
+
+ template<typename T, typename A>
+ inline RemoteIndices<T,A>::RemoteIndices(const ParallelIndexSet& source,
+ const ParallelIndexSet& destination,
+ const MPI_Comm& comm,
+ const std::vector<int>& neighbours,
+ bool includeSelf_)
+ : source_(&source), target_(&destination), comm_(comm),
+ sourceSeqNo_(-1), destSeqNo_(-1), publicIgnored(false), firstBuild(true),
+ includeSelf(includeSelf_)
+ {
+ setNeighbours(neighbours);
+ }
+
+ template<typename T, typename A>
+ void RemoteIndices<T,A>::setIncludeSelf(bool b)
+ {
+ includeSelf=b;
+ }
+
+ template<typename T, typename A>
+ RemoteIndices<T,A>::RemoteIndices()
+ : source_(0), target_(0), sourceSeqNo_(-1),
+ destSeqNo_(-1), publicIgnored(false), firstBuild(true)
+ {}
+
+ template<class T, typename A>
+ void RemoteIndices<T,A>::setIndexSets(const ParallelIndexSet& source,
+ const ParallelIndexSet& destination,
+ const MPI_Comm& comm,
+ const std::vector<int>& neighbours)
+ {
+ free();
+ source_ = &source;
+ target_ = &destination;
+ comm_ = comm;
+ firstBuild = true;
+ setNeighbours(neighbours);
+ }
+
+ template<typename T, typename A>
+ const typename RemoteIndices<T,A>::ParallelIndexSet&
+ RemoteIndices<T,A>::sourceIndexSet() const
+ {
+ return *source_;
+ }
+
+
+ template<typename T, typename A>
+ const typename RemoteIndices<T,A>::ParallelIndexSet&
+ RemoteIndices<T,A>::destinationIndexSet() const
+ {
+ return *target_;
+ }
+
+
+ template<typename T, typename A>
+ RemoteIndices<T,A>::~RemoteIndices()
+ {
+ free();
+ }
+
+ template<typename T, typename A>
+ template<bool ignorePublic>
+ inline void RemoteIndices<T,A>::packEntries(IndexPair<GlobalIndex,LocalIndex>** pairs,
+ const ParallelIndexSet& indexSet,
+ char* p_out, MPI_Datatype type,
+ int bufferSize,
+ int *position, int n)
+ {
+ // fill with own indices
+ typedef typename ParallelIndexSet::const_iterator const_iterator;
+ typedef IndexPair<GlobalIndex,LocalIndex> PairType;
+ const const_iterator end = indexSet.end();
+
+ //Now pack the source indices
+ int i=0;
+ for(const_iterator index = indexSet.begin(); index != end; ++index)
+ if(ignorePublic || index->local().isPublic()) {
+
+ MPI_Pack(const_cast<PairType*>(&(*index)), 1,
+ type,
+ p_out, bufferSize, position, comm_);
+ pairs[i++] = const_cast<PairType*>(&(*index));
+
+ }
+ assert(i==n);
+ }
+
+ template<typename T, typename A>
+ inline int RemoteIndices<T,A>::noPublic(const ParallelIndexSet& indexSet)
+ {
+ typedef typename ParallelIndexSet::const_iterator const_iterator;
+
+ int noPublic=0;
+
+ const const_iterator end=indexSet.end();
+ for(const_iterator index=indexSet.begin(); index!=end; ++index)
+ if(index->local().isPublic())
+ noPublic++;
+
+ return noPublic;
+
+ }
+
+
+ template<typename T, typename A>
+ inline void RemoteIndices<T,A>::unpackCreateRemote(char* p_in, PairType** sourcePairs,
+ PairType** destPairs, int remoteProc,
+ int sourcePublish, int destPublish,
+ int bufferSize, bool sendTwo,
+ bool fromOurSelf)
+ {
+
+ // unpack the number of indices we received
+ int noRemoteSource=-1, noRemoteDest=-1;
+ char twoIndexSets=0;
+ int position=0;
+ // Did we receive two index sets?
+ MPI_Unpack(p_in, bufferSize, &position, &twoIndexSets, 1, MPI_CHAR, comm_);
+ // The number of source indices received
+ MPI_Unpack(p_in, bufferSize, &position, &noRemoteSource, 1, MPI_INT, comm_);
+ // The number of destination indices received
+ MPI_Unpack(p_in, bufferSize, &position, &noRemoteDest, 1, MPI_INT, comm_);
+
+
+ // Indices for which we receive
+ RemoteIndexList* receive= new RemoteIndexList();
+ // Indices for which we send
+ RemoteIndexList* send=0;
+
+ MPI_Datatype type= MPITraits<PairType>::getType();
+
+ if(!twoIndexSets) {
+ if(sendTwo) {
+ send = new RemoteIndexList();
+ // Create both remote index sets simultaneously
+ unpackIndices(*send, *receive, noRemoteSource, sourcePairs, sourcePublish,
+ destPairs, destPublish, p_in, type, &position, bufferSize);
+ }else{
+ // we only need one list
+ unpackIndices(*receive, noRemoteSource, sourcePairs, sourcePublish,
+ p_in, type, &position, bufferSize, fromOurSelf);
+ send=receive;
+ }
+ }else{
+
+ int oldPos=position;
+ // Two index sets received
+ unpackIndices(*receive, noRemoteSource, destPairs, destPublish,
+ p_in, type, &position, bufferSize, fromOurSelf);
+ if(!sendTwo)
+ //unpack source entries again as destination entries
+ position=oldPos;
+
+ send = new RemoteIndexList();
+ unpackIndices(*send, noRemoteDest, sourcePairs, sourcePublish,
+ p_in, type, &position, bufferSize, fromOurSelf);
+ }
+
+ if(receive->empty() && send->empty()) {
+ if(send==receive) {
+ delete send;
+ }else{
+ delete send;
+ delete receive;
+ }
+ }else{
+ remoteIndices_.insert(std::make_pair(remoteProc,
+ std::make_pair(send,receive)));
+ }
+ }
+
+
+ template<typename T, typename A>
+ template<bool ignorePublic>
+ inline void RemoteIndices<T,A>::buildRemote(bool includeSelf)
+ {
+ // Processor configuration
+ int rank, procs;
+ MPI_Comm_rank(comm_, &rank);
+ MPI_Comm_size(comm_, &procs);
+
+ // number of local indices to publish
+ // The indices of the destination will be send.
+ int sourcePublish, destPublish;
+
+ // Do we need to send two index sets?
+ char sendTwo = (source_ != target_);
+
+ if(procs==1 && !(sendTwo || includeSelf))
+ // Nothing to communicate
+ return;
+
+ sourcePublish = (ignorePublic) ? source_->size() : noPublic(*source_);
+
+ if(sendTwo)
+ destPublish = (ignorePublic) ? target_->size() : noPublic(*target_);
+ else
+ // we only need to send one set of indices
+ destPublish = 0;
+
+ int maxPublish, publish=sourcePublish+destPublish;
+
+ // Calucate maximum number of indices send
+ MPI_Allreduce(&publish, &maxPublish, 1, MPI_INT, MPI_MAX, comm_);
+
+ // allocate buffers
+ typedef IndexPair<GlobalIndex,LocalIndex> PairType;
+
+ PairType** destPairs;
+ PairType** sourcePairs = new PairType*[sourcePublish>0 ? sourcePublish : 1];
+
+ if(sendTwo)
+ destPairs = new PairType*[destPublish>0 ? destPublish : 1];
+ else
+ destPairs=sourcePairs;
+
+ char** buffer = new char*[2];
+ int bufferSize;
+ int position=0;
+ int intSize;
+ int charSize;
+
+ // calculate buffer size
+ MPI_Datatype type = MPITraits<PairType>::getType();
+
+ MPI_Pack_size(maxPublish, type, comm_,
+ &bufferSize);
+ MPI_Pack_size(1, MPI_INT, comm_,
+ &intSize);
+ MPI_Pack_size(1, MPI_CHAR, comm_,
+ &charSize);
+ // Our message will contain the following:
+ // a bool wether two index sets where sent
+ // the size of the source and the dest indexset,
+ // then the source and destination indices
+ bufferSize += 2 * intSize + charSize;
+
+ if(bufferSize<=0) bufferSize=1;
+
+ buffer[0] = new char[bufferSize];
+ buffer[1] = new char[bufferSize];
+
+
+ // pack entries into buffer[0], p_out below!
+ MPI_Pack(&sendTwo, 1, MPI_CHAR, buffer[0], bufferSize, &position,
+ comm_);
+
+ // The number of indices we send for each index set
+ MPI_Pack(&sourcePublish, 1, MPI_INT, buffer[0], bufferSize, &position,
+ comm_);
+ MPI_Pack(&destPublish, 1, MPI_INT, buffer[0], bufferSize, &position,
+ comm_);
+
+ // Now pack the source indices and setup the destination pairs
+ packEntries<ignorePublic>(sourcePairs, *source_, buffer[0], type,
+ bufferSize, &position, sourcePublish);
+ // If necessary send the dest indices and setup the source pairs
+ if(sendTwo)
+ packEntries<ignorePublic>(destPairs, *target_, buffer[0], type,
+ bufferSize, &position, destPublish);
+
+
+ // Update remote indices for ourself
+ if(sendTwo|| includeSelf)
+ unpackCreateRemote(buffer[0], sourcePairs, destPairs, rank, sourcePublish,
+ destPublish, bufferSize, sendTwo, includeSelf);
+
+ neighbourIds.erase(rank);
+
+ if(neighbourIds.size()==0)
+ {
+ Dune::dvverb<<rank<<": Sending messages in a ring"<<std::endl;
+ // send messages in ring
+ for(int proc=1; proc<procs; proc++) {
+ // pointers to the current input and output buffers
+ char* p_out = buffer[1-(proc%2)];
+ char* p_in = buffer[proc%2];
+
+ MPI_Status status;
+ if(rank%2==0) {
+ MPI_Ssend(p_out, bufferSize, MPI_PACKED, (rank+1)%procs,
+ commTag_, comm_);
+ MPI_Recv(p_in, bufferSize, MPI_PACKED, (rank+procs-1)%procs,
+ commTag_, comm_, &status);
+ }else{
+ MPI_Recv(p_in, bufferSize, MPI_PACKED, (rank+procs-1)%procs,
+ commTag_, comm_, &status);
+ MPI_Ssend(p_out, bufferSize, MPI_PACKED, (rank+1)%procs,
+ commTag_, comm_);
+ }
+
+
+ // The process these indices are from
+ int remoteProc = (rank+procs-proc)%procs;
+
+ unpackCreateRemote(p_in, sourcePairs, destPairs, remoteProc, sourcePublish,
+ destPublish, bufferSize, sendTwo);
+
+ }
+
+ }
+ else
+ {
+ MPI_Request* requests=new MPI_Request[neighbourIds.size()];
+ MPI_Request* req=requests;
+
+ typedef typename std::set<int>::size_type size_type;
+ size_type noNeighbours=neighbourIds.size();
+
+ // setup sends
+ for(std::set<int>::iterator neighbour=neighbourIds.begin();
+ neighbour!= neighbourIds.end(); ++neighbour) {
+ // Only send the information to the neighbouring processors
+ MPI_Issend(buffer[0], position , MPI_PACKED, *neighbour, commTag_, comm_, req++);
+ }
+
+ //Test for received messages
+
+ for(size_type received=0; received <noNeighbours; ++received)
+ {
+ MPI_Status status;
+ // probe for next message
+ MPI_Probe(MPI_ANY_SOURCE, commTag_, comm_, &status);
+ int remoteProc=status.MPI_SOURCE;
+ int size;
+ MPI_Get_count(&status, MPI_PACKED, &size);
+ // receive message
+ MPI_Recv(buffer[1], size, MPI_PACKED, remoteProc,
+ commTag_, comm_, &status);
+
+ unpackCreateRemote(buffer[1], sourcePairs, destPairs, remoteProc, sourcePublish,
+ destPublish, bufferSize, sendTwo);
+ }
+ // wait for completion of pending requests
+ MPI_Status* statuses = new MPI_Status[neighbourIds.size()];
+
+ if(MPI_ERR_IN_STATUS==MPI_Waitall(neighbourIds.size(), requests, statuses)) {
+ for(size_type i=0; i < neighbourIds.size(); ++i)
+ if(statuses[i].MPI_ERROR!=MPI_SUCCESS) {
+ std::cerr<<rank<<": MPI_Error occurred while receiving message."<<std::endl;
+ MPI_Abort(comm_, 999);
+ }
+ }
+ delete[] requests;
+ delete[] statuses;
+ }
+
+
+ // delete allocated memory
+ if(destPairs!=sourcePairs)
+ delete[] destPairs;
+
+ delete[] sourcePairs;
+ delete[] buffer[0];
+ delete[] buffer[1];
+ delete[] buffer;
+ }
+
+ template<typename T, typename A>
+ inline void RemoteIndices<T,A>::unpackIndices(RemoteIndexList& remote,
+ int remoteEntries,
+ PairType** local,
+ int localEntries,
+ char* p_in,
+ MPI_Datatype type,
+ int* position,
+ int bufferSize,
+ bool fromOurSelf)
+ {
+ if(remoteEntries==0)
+ return;
+
+ PairType index(-1);
+ MPI_Unpack(p_in, bufferSize, position, &index, 1,
+ type, comm_);
+ GlobalIndex oldGlobal=index.global();
+ int n_in=0, localIndex=0;
+
+ //Check if we know the global index
+ while(localIndex<localEntries) {
+ if(local[localIndex]->global()==index.global()) {
+ int oldLocalIndex=localIndex;
+
+ while(localIndex<localEntries &&
+ local[localIndex]->global()==index.global()) {
+ if(!fromOurSelf || index.local().attribute() !=
+ local[localIndex]->local().attribute())
+ // if index is from us it has to have a different attribute
+ remote.push_back(RemoteIndex(index.local().attribute(),
+ local[localIndex]));
+ localIndex++;
+ }
+
+ // unpack next remote index
+ if((++n_in) < remoteEntries) {
+ MPI_Unpack(p_in, bufferSize, position, &index, 1,
+ type, comm_);
+ if(index.global()==oldGlobal)
+ // Restart comparison for the same global indices
+ localIndex=oldLocalIndex;
+ else
+ oldGlobal=index.global();
+ }else{
+ // No more received indices
+ break;
+ }
+ continue;
+ }
+
+ if (local[localIndex]->global()<index.global()) {
+ // compare with next entry in our list
+ ++localIndex;
+ }else{
+ // We do not know the index, unpack next
+ if((++n_in) < remoteEntries) {
+ MPI_Unpack(p_in, bufferSize, position, &index, 1,
+ type, comm_);
+ oldGlobal=index.global();
+ }else
+ // No more received indices
+ break;
+ }
+ }
+
+ // Unpack the other received indices without doing anything
+ while(++n_in < remoteEntries)
+ MPI_Unpack(p_in, bufferSize, position, &index, 1,
+ type, comm_);
+ }
+
+
+ template<typename T, typename A>
+ inline void RemoteIndices<T,A>::unpackIndices(RemoteIndexList& send,
+ RemoteIndexList& receive,
+ int remoteEntries,
+ PairType** localSource,
+ int localSourceEntries,
+ PairType** localDest,
+ int localDestEntries,
+ char* p_in,
+ MPI_Datatype type,
+ int* position,
+ int bufferSize)
+ {
+ int n_in=0, sourceIndex=0, destIndex=0;
+
+ //Check if we know the global index
+ while(n_in<remoteEntries && (sourceIndex<localSourceEntries || destIndex<localDestEntries)) {
+ // Unpack next index
+ PairType index;
+ MPI_Unpack(p_in, bufferSize, position, &index, 1,
+ type, comm_);
+ n_in++;
+
+ // Advance until global index in localSource and localDest are >= than the one in the unpacked index
+ while(sourceIndex<localSourceEntries && localSource[sourceIndex]->global()<index.global())
+ sourceIndex++;
+
+ while(destIndex<localDestEntries && localDest[destIndex]->global()<index.global())
+ destIndex++;
+
+ // Add a remote index if we found the global index.
+ if(sourceIndex<localSourceEntries && localSource[sourceIndex]->global()==index.global())
+ send.push_back(RemoteIndex(index.local().attribute(),
+ localSource[sourceIndex]));
+
+ if(destIndex < localDestEntries && localDest[destIndex]->global() == index.global())
+ receive.push_back(RemoteIndex(index.local().attribute(),
+ localDest[sourceIndex]));
+ }
+
+ }
+
+ template<typename T, typename A>
+ inline void RemoteIndices<T,A>::free()
+ {
+ typedef typename RemoteIndexMap::iterator Iterator;
+ Iterator lend = remoteIndices_.end();
+ for(Iterator lists=remoteIndices_.begin(); lists != lend; ++lists) {
+ if(lists->second.first==lists->second.second) {
+ // there is only one remote index list.
+ delete lists->second.first;
+ }else{
+ delete lists->second.first;
+ delete lists->second.second;
+ }
+ }
+ remoteIndices_.clear();
+ firstBuild=true;
+ }
+
+ template<typename T, typename A>
+ inline int RemoteIndices<T,A>::neighbours() const
+ {
+ return remoteIndices_.size();
+ }
+
+ template<typename T, typename A>
+ template<bool ignorePublic>
+ inline void RemoteIndices<T,A>::rebuild()
+ {
+ // Test wether a rebuild is Needed.
+ if(firstBuild ||
+ ignorePublic!=publicIgnored || !
+ isSynced()) {
+ free();
+
+ buildRemote<ignorePublic>(includeSelf);
+
+ sourceSeqNo_ = source_->seqNo();
+ destSeqNo_ = target_->seqNo();
+ firstBuild=false;
+ publicIgnored=ignorePublic;
+ }
+
+
+ }
+
+ template<typename T, typename A>
+ inline bool RemoteIndices<T,A>::isSynced() const
+ {
+ return sourceSeqNo_==source_->seqNo() && destSeqNo_ ==target_->seqNo();
+ }
+
+ template<typename T, typename A>
+ template<bool mode, bool send>
+ RemoteIndexListModifier<T,A,mode> RemoteIndices<T,A>::getModifier(int process)
+ {
+
+ // The user are on their own now!
+ // We assume they know what they are doing and just set the
+ // remote indices to synced status.
+ sourceSeqNo_ = source_->seqNo();
+ destSeqNo_ = target_->seqNo();
+
+ typename RemoteIndexMap::iterator found = remoteIndices_.find(process);
+
+ if(found == remoteIndices_.end())
+ {
+ if(source_ != target_)
+ found = remoteIndices_.insert(found, std::make_pair(process,
+ std::make_pair(new RemoteIndexList(),
+ new RemoteIndexList())));
+ else{
+ RemoteIndexList* rlist = new RemoteIndexList();
+ found = remoteIndices_.insert(found,
+ std::make_pair(process,
+ std::make_pair(rlist, rlist)));
+ }
+ }
+
+ firstBuild = false;
+
+ if(send)
+ return RemoteIndexListModifier<T,A,mode>(*source_, *(found->second.first));
+ else
+ return RemoteIndexListModifier<T,A,mode>(*target_, *(found->second.second));
+ }
+
+ template<typename T, typename A>
+ inline typename RemoteIndices<T,A>::const_iterator
+ RemoteIndices<T,A>::find(int proc) const
+ {
+ return remoteIndices_.find(proc);
+ }
+
+ template<typename T, typename A>
+ inline typename RemoteIndices<T,A>::const_iterator
+ RemoteIndices<T,A>::begin() const
+ {
+ return remoteIndices_.begin();
+ }
+
+ template<typename T, typename A>
+ inline typename RemoteIndices<T,A>::const_iterator
+ RemoteIndices<T,A>::end() const
+ {
+ return remoteIndices_.end();
+ }
+
+
+ template<typename T, typename A>
+ bool RemoteIndices<T,A>::operator==(const RemoteIndices& ri)
+ {
+ if(neighbours()!=ri.neighbours())
+ return false;
+
+ typedef RemoteIndexList RList;
+ typedef typename std::map<int,std::pair<RList*,RList*> >::const_iterator const_iterator;
+
+ const const_iterator rend = remoteIndices_.end();
+
+ for(const_iterator rindex = remoteIndices_.begin(), rindex1=ri.remoteIndices_.begin(); rindex!=rend; ++rindex, ++rindex1) {
+ if(rindex->first != rindex1->first)
+ return false;
+ if(*(rindex->second.first) != *(rindex1->second.first))
+ return false;
+ if(*(rindex->second.second) != *(rindex1->second.second))
+ return false;
+ }
+ return true;
+ }
+
+ template<class T, class A, bool mode>
+ RemoteIndexListModifier<T,A,mode>::RemoteIndexListModifier(const ParallelIndexSet& indexSet,
+ RemoteIndexList& rList)
+ : rList_(&rList), indexSet_(&indexSet), iter_(rList.beginModify()), end_(rList.end()), first_(true)
+ {
+ if(MODIFYINDEXSET) {
+ assert(indexSet_);
+ for(ConstIterator iter=iter_; iter != end_; ++iter)
+ glist_.push_back(iter->localIndexPair().global());
+ giter_ = glist_.beginModify();
+ }
+ }
+
+ template<typename T, typename A, bool mode>
+ RemoteIndexListModifier<T,A,mode>::RemoteIndexListModifier(const RemoteIndexListModifier<T,A,mode>& other)
+ : rList_(other.rList_), indexSet_(other.indexSet_),
+ glist_(other.glist_), iter_(other.iter_), giter_(other.giter_), end_(other.end_),
+ first_(other.first_), last_(other.last_)
+ {}
+
+ template<typename T, typename A, bool mode>
+ inline void RemoteIndexListModifier<T,A,mode>::repairLocalIndexPointers() throw(InvalidIndexSetState)
+ {
+ if(MODIFYINDEXSET) {
+ // repair pointers to local index set.
+#ifdef DUNE_ISTL_WITH_CHECKING
+ if(indexSet_->state()!=GROUND)
+ DUNE_THROW(InvalidIndexSetState, "Index has to be in ground mode for repairing pointers to indices");
+#endif
+ typedef typename ParallelIndexSet::const_iterator IndexIterator;
+ typedef typename GlobalList::const_iterator GlobalIterator;
+ typedef typename RemoteIndexList::iterator Iterator;
+ GlobalIterator giter = glist_.begin();
+ IndexIterator index = indexSet_->begin();
+
+ for(Iterator iter=rList_->begin(); iter != end_; ++iter) {
+ while(index->global()<*giter) {
+ ++index;
+#ifdef DUNE_ISTL_WITH_CHECKING
+ if(index == indexSet_->end())
+ DUNE_THROW(InvalidPosition, "No such global index in set!");
+#endif
+ }
+
+#ifdef DUNE_ISTL_WITH_CHECKING
+ if(index->global() != *giter)
+ DUNE_THROW(InvalidPosition, "No such global index in set!");
+#endif
+ iter->localIndex_ = &(*index);
+ }
+ }
+ }
+
+ template<typename T, typename A, bool mode>
+ inline void RemoteIndexListModifier<T,A,mode>::insert(const RemoteIndex& index) throw(InvalidPosition)
+ {
+ dune_static_assert(!mode,"Not allowed if the mode indicates that new indices"
+ "might be added to the underlying index set. Use "
+ "insert(const RemoteIndex&, const GlobalIndex&) instead");
+
+#ifdef DUNE_ISTL_WITH_CHECKING
+ if(!first_ && index.localIndexPair().global()<last_)
+ DUNE_THROW(InvalidPosition, "Modifcation of remote indices have to occur with ascending global index.");
+#endif
+ // Move to the correct position
+ while(iter_ != end_ && iter_->localIndexPair().global() < index.localIndexPair().global()) {
+ ++iter_;
+ }
+
+ // No duplicate entries allowed
+ assert(iter_==end_ || iter_->localIndexPair().global() != index.localIndexPair().global());
+ iter_.insert(index);
+ last_ = index.localIndexPair().global();
+ first_ = false;
+ }
+
+ template<typename T, typename A, bool mode>
+ inline void RemoteIndexListModifier<T,A,mode>::insert(const RemoteIndex& index, const GlobalIndex& global) throw(InvalidPosition)
+ {
+ dune_static_assert(mode,"Not allowed if the mode indicates that no new indices"
+ "might be added to the underlying index set. Use "
+ "insert(const RemoteIndex&) instead");
+#ifdef DUNE_ISTL_WITH_CHECKING
+ if(!first_ && global<last_)
+ DUNE_THROW(InvalidPosition, "Modification of remote indices have to occur with ascending global index.");
+#endif
+ // Move to the correct position
+ while(iter_ != end_ && *giter_ < global) {
+ ++giter_;
+ ++iter_;
+ }
+
+ // No duplicate entries allowed
+ assert(iter_->localIndexPair().global() != global);
+ iter_.insert(index);
+ giter_.insert(global);
+
+ last_ = global;
+ first_ = false;
+ }
+
+ template<typename T, typename A, bool mode>
+ bool RemoteIndexListModifier<T,A,mode>::remove(const GlobalIndex& global) throw(InvalidPosition)
+ {
+#ifdef DUNE_ISTL_WITH_CHECKING
+ if(!first_ && global<last_)
+ DUNE_THROW(InvalidPosition, "Modifcation of remote indices have to occur with ascending global index.");
+#endif
+
+ bool found= false;
+
+ if(MODIFYINDEXSET) {
+ // Move to the correct position
+ while(iter_!=end_ && *giter_< global) {
+ ++giter_;
+ ++iter_;
+ }
+ if(*giter_ == global) {
+ giter_.remove();
+ iter_.remove();
+ found=true;
+ }
+ }else{
+ while(iter_!=end_ && iter_->localIndexPair().global() < global)
+ ++iter_;
+
+ if(iter_->localIndexPair().global()==global) {
+ iter_.remove();
+ found = true;
+ }
+ }
+
+ last_ = global;
+ first_ = false;
+ return found;
+ }
+
+ template<typename T, typename A>
+ template<bool send>
+ inline typename RemoteIndices<T,A>::CollectiveIteratorT RemoteIndices<T,A>::iterator() const
+ {
+ return CollectiveIterator<T,A>(remoteIndices_, send);
+ }
+
+ template<typename T, typename A>
+ inline MPI_Comm RemoteIndices<T,A>::communicator() const
+ {
+ return comm_;
+
+ }
+
+ template<typename T, typename A>
+ CollectiveIterator<T,A>::CollectiveIterator(const RemoteIndexMap& pmap, bool send)
+ {
+ typedef typename RemoteIndexMap::const_iterator const_iterator;
+
+ const const_iterator end=pmap.end();
+ for(const_iterator process=pmap.begin(); process != end; ++process) {
+ const RemoteIndexList* list = send ? process->second.first : process->second.second;
+ typedef typename RemoteIndexList::const_iterator iterator;
+ map_.insert(std::make_pair(process->first,
+ std::pair<iterator, const iterator>(list->begin(), list->end())));
+ }
+ }
+
+ template<typename T, typename A>
+ inline void CollectiveIterator<T,A>::advance(const GlobalIndex& index)
+ {
+ typedef typename Map::iterator iterator;
+ typedef typename Map::const_iterator const_iterator;
+ const const_iterator end = map_.end();
+
+ for(iterator iter = map_.begin(); iter != end;) {
+ // Step the iterator until we are >= index
+ typename RemoteIndexList::const_iterator current = iter->second.first;
+ typename RemoteIndexList::const_iterator rend = iter->second.second;
+ RemoteIndex remoteIndex;
+ if(current != rend)
+ remoteIndex = *current;
+
+ while(iter->second.first!=iter->second.second && iter->second.first->localIndexPair().global()<index)
+ ++(iter->second.first);
+
+ // erase from the map if there are no more entries.
+ if(iter->second.first == iter->second.second)
+ map_.erase(iter++);
+ else{
+ ++iter;
+ }
+ }
+ index_=index;
+ noattribute=true;
+ }
+
+ template<typename T, typename A>
+ inline void CollectiveIterator<T,A>::advance(const GlobalIndex& index,
+ const Attribute& attribute)
+ {
+ typedef typename Map::iterator iterator;
+ typedef typename Map::const_iterator const_iterator;
+ const const_iterator end = map_.end();
+
+ for(iterator iter = map_.begin(); iter != end;) {
+ // Step the iterator until we are >= index
+ typename RemoteIndexList::const_iterator current = iter->second.first;
+ typename RemoteIndexList::const_iterator rend = iter->second.second;
+ RemoteIndex remoteIndex;
+ if(current != rend)
+ remoteIndex = *current;
+
+ // Move to global index or bigger
+ while(iter->second.first!=iter->second.second && iter->second.first->localIndexPair().global()<index)
+ ++(iter->second.first);
+
+ // move to attribute or bigger
+ while(iter->second.first!=iter->second.second
+ && iter->second.first->localIndexPair().global()==index
+ && iter->second.first->localIndexPair().local().attribute()<attribute)
+ ++(iter->second.first);
+
+ // erase from the map if there are no more entries.
+ if(iter->second.first == iter->second.second)
+ map_.erase(iter++);
+ else{
+ ++iter;
+ }
+ }
+ index_=index;
+ attribute_=attribute;
+ noattribute=false;
+ }
+
+ template<typename T, typename A>
+ inline CollectiveIterator<T,A>& CollectiveIterator<T,A>::operator++()
+ {
+ typedef typename Map::iterator iterator;
+ typedef typename Map::const_iterator const_iterator;
+ const const_iterator end = map_.end();
+
+ for(iterator iter = map_.begin(); iter != end;) {
+ // Step the iterator until we are >= index
+ typename RemoteIndexList::const_iterator current = iter->second.first;
+ typename RemoteIndexList::const_iterator rend = iter->second.second;
+
+ // move all iterators pointing to the current global index to next value
+ if(iter->second.first->localIndexPair().global()==index_ &&
+ (noattribute || iter->second.first->localIndexPair().local().attribute() == attribute_))
+ ++(iter->second.first);
+
+ // erase from the map if there are no more entries.
+ if(iter->second.first == iter->second.second)
+ map_.erase(iter++);
+ else{
+ ++iter;
+ }
+ }
+ return *this;
+ }
+
+ template<typename T, typename A>
+ inline bool CollectiveIterator<T,A>::empty()
+ {
+ return map_.empty();
+ }
+
+ template<typename T, typename A>
+ inline typename CollectiveIterator<T,A>::iterator
+ CollectiveIterator<T,A>::begin()
+ {
+ if(noattribute)
+ return iterator(map_.begin(), map_.end(), index_);
+ else
+ return iterator(map_.begin(), map_.end(), index_,
+ attribute_);
+ }
+
+ template<typename T, typename A>
+ inline typename CollectiveIterator<T,A>::iterator
+ CollectiveIterator<T,A>::end()
+ {
+ return iterator(map_.end(), map_.end(), index_);
+ }
+
+ template<typename TG, typename TA>
+ inline std::ostream& operator<<(std::ostream& os, const RemoteIndex<TG,TA>& index)
+ {
+ os<<"[global="<<index.localIndexPair().global()<<", remote attribute="<<index.attribute()<<" local attribute="<<index.localIndexPair().local().attribute()<<"]";
+ return os;
+ }
+
+ template<typename T, typename A>
+ inline std::ostream& operator<<(std::ostream& os, const RemoteIndices<T,A>& indices)
+ {
+ int rank;
+ MPI_Comm_rank(indices.comm_, &rank);
+
+ typedef typename RemoteIndices<T,A>::RemoteIndexList RList;
+ typedef typename std::map<int,std::pair<RList*,RList*> >::const_iterator const_iterator;
+
+ const const_iterator rend = indices.remoteIndices_.end();
+
+ for(const_iterator rindex = indices.remoteIndices_.begin(); rindex!=rend; ++rindex) {
+ os<<rank<<": Prozess "<<rindex->first<<":";
+
+ if(!rindex->second.first->empty()) {
+ os<<" send:";
+
+ const typename RList::const_iterator send= rindex->second.first->end();
+
+ for(typename RList::const_iterator index = rindex->second.first->begin();
+ index != send; ++index)
+ os<<*index<<" ";
+ os<<std::endl;
+ }
+ if(!rindex->second.second->empty()) {
+ os<<rank<<": Prozess "<<rindex->first<<": "<<"receive: ";
+
+ const typename RList::const_iterator rend= rindex->second.second->end();
+
+ for(typename RList::const_iterator index = rindex->second.second->begin();
+ index != rend; ++index)
+ os<<*index<<" ";
+ }
+ os<<std::endl<<std::flush;
+ }
+ return os;
+ }
+ /** @} */
+}
+
+#endif
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+#ifndef DUNE_SELECTION_HH
+#define DUNE_SELECTION_HH
+
+#include "indexset.hh"
+#include <dune/common/iteratorfacades.hh>
+
+namespace Dune
+{
+ /** @addtogroup Common_Parallel
+ *
+ * @{
+ */
+ /**
+ * @file
+ * @brief Provides classes for selecting
+ * indices based on attribute flags.
+ * @author Markus Blatt
+ */
+
+ /**
+ * @brief A const iterator over an uncached selection.
+ */
+ template<typename TS, typename TG, typename TL, int N>
+ class SelectionIterator
+ {
+ public:
+ /**
+ * @brief The type of the Set of attributes.
+ *
+ * It has to provide a static method
+ * \code bool contains(AttributeType a); \endcode
+ * that returns true if a is in the set.
+ * Such types are EnumItem, EnumRange, Combine.
+ */
+ typedef TS AttributeSet;
+
+ /**
+ * @brief The type of the underlying index set.
+ */
+ typedef Dune::ParallelIndexSet<TG,TL,N> ParallelIndexSet;
+
+ //typedef typename ParallelIndexSet::const_iterator ParallelIndexSetIterator;
+
+ typedef ConstArrayListIterator<IndexPair<TG,TL>, N, std::allocator<Dune::IndexPair<TG,TL> > > ParallelIndexSetIterator;
+ /**
+ * @brief Constructor.
+ * @param iter The iterator over the index set.
+ * @param end The iterator over the index set positioned at the end.
+ */
+ SelectionIterator(const ParallelIndexSetIterator& iter, const ParallelIndexSetIterator& end)
+ : iter_(iter), end_(end)
+ {
+ // Step to the first valid entry
+ while(iter_!=end_ && !AttributeSet::contains(iter_->local().attribute()))
+ ++iter_;
+ }
+
+ void operator++()
+ {
+ assert(iter_!=end_);
+ for(++iter_; iter_!=end_; ++iter_)
+ if(AttributeSet::contains(iter_->local().attribute()))
+ break;
+ }
+
+
+ uint32_t operator*() const
+ {
+ return iter_->local().local();
+ }
+
+ bool operator==(const SelectionIterator<TS,TG,TL,N>& other) const
+ {
+ return iter_ == other.iter_;
+ }
+
+ bool operator!=(const SelectionIterator<TS,TG,TL,N>& other) const
+ {
+ return iter_ != other.iter_;
+ }
+
+ private:
+ ParallelIndexSetIterator iter_;
+ const ParallelIndexSetIterator end_;
+ };
+
+
+ /**
+ * @brief An uncached selection of indices.
+ */
+ template<typename TS, typename TG, typename TL, int N>
+ class UncachedSelection
+ {
+ public:
+ /**
+ * @brief The type of the Set of attributes.
+ *
+ * It has to provide a static method
+ * \code bool contains(AttributeType a); \endcode
+ * that returns true if a is in the set.
+ * Such types are EnumItem, EnumRange, Combine.
+ */
+ typedef TS AttributeSet;
+
+ /**
+ * @brief The type of the global index of the underlying index set.
+ */
+ typedef TG GlobalIndex;
+
+ /**
+ * @brief The type of the local index of the underlying index set.
+ *
+ * It has to provide a function
+ * \code AttributeType attribute(); \endcode
+ */
+ typedef TL LocalIndex;
+
+ /**
+ * @brief The type of the underlying index set.
+ */
+ typedef Dune::ParallelIndexSet<GlobalIndex,LocalIndex,N> ParallelIndexSet;
+
+ /**
+ * @brief The type of the iterator of the selected indices.
+ */
+ typedef SelectionIterator<TS,TG,TL,N> iterator;
+
+ /**
+ * @brief The type of the iterator of the selected indices.
+ */
+ typedef iterator const_iterator;
+
+ UncachedSelection()
+ : indexSet_()
+ {}
+
+ UncachedSelection(const ParallelIndexSet& indexset)
+ : indexSet_(&indexset)
+ {}
+ /**
+ * @brief Set the index set of the selection.
+ * @param indexset The index set to use.
+ */
+ void setIndexSet(const ParallelIndexSet& indexset);
+
+ /**
+ * @brief Get the index set we are a selection for.
+ */
+ //const ParallelIndexSet& indexSet() const;
+
+ /**
+ * @brief Get an iterator over the selected indices.
+ * @return An iterator positioned at the first selected index.
+ */
+ const_iterator begin() const;
+
+ /**
+ * @brief Get an iterator over the selected indices.
+ * @return An iterator positioned at the first selected index.
+ */
+ const_iterator end() const;
+
+
+ private:
+ const ParallelIndexSet* indexSet_;
+
+ };
+
+ /**
+ * @brief A cached selection of indices.
+ */
+ template<typename TS, typename TG, typename TL, int N>
+ class Selection
+ {
+ public:
+ /**
+ * @brief The type of the set of attributes.
+ *
+ * It has to provide a static method
+ * \code bool contains(AttributeType a); \endcode
+ * that returns true if a is in the set.
+ * Such types are EnumItem, EnumRange, Combine.
+ */
+ typedef TS AttributeSet;
+
+ /**
+ * @brief The type of the global index of the underlying index set.
+ */
+ typedef TG GlobalIndex;
+
+ /**
+ * @brief The type of the local index of the underlying index set.
+ *
+ * It has to provide a function
+ * \code AttributeType attribute(); \endcode
+ */
+ typedef TL LocalIndex;
+
+ /**
+ * @brief The type of the underlying index set.
+ */
+ typedef Dune::ParallelIndexSet<GlobalIndex,LocalIndex,N> ParallelIndexSet;
+
+ /**
+ * @brief The type of the iterator of the selected indices.
+ */
+ typedef uint32_t* iterator;
+
+ /**
+ * @brief The type of the iterator of the selected indices.
+ */
+ typedef uint32_t* const_iterator;
+
+ Selection()
+ : selected_()
+ {}
+
+ Selection(const ParallelIndexSet& indexset)
+ : selected_(), size_(0), built_(false)
+ {
+ setIndexSet(indexset);
+ }
+
+ ~Selection();
+
+ /**
+ * @brief Set the index set of the selection.
+ * @param indexset The index set to use.
+ */
+ void setIndexSet(const ParallelIndexSet& indexset);
+
+ /**
+ * @brief Free allocated memory.
+ */
+ void free();
+
+ /**
+ * @brief Get the index set we are a selection for.
+ */
+ //IndexSet indexSet() const;
+
+ /**
+ * @brief Get an iterator over the selected indices.
+ * @return An iterator positioned at the first selected index.
+ */
+ const_iterator begin() const;
+
+ /**
+ * @brief Get an iterator over the selected indices.
+ * @return An iterator positioned at the first selected index.
+ */
+ const_iterator end() const;
+
+
+ private:
+ uint32_t* selected_;
+ size_t size_;
+ bool built_;
+
+ };
+
+ template<typename TS, typename TG, typename TL, int N>
+ inline void Selection<TS,TG,TL,N>::setIndexSet(const ParallelIndexSet& indexset)
+ {
+ if(built_)
+ free();
+
+ // Count the number of entries the selection has to hold
+ typedef typename ParallelIndexSet::const_iterator const_iterator;
+ const const_iterator end = indexset.end();
+ int entries = 0;
+
+ for(const_iterator index = indexset.begin(); index != end; ++index)
+ if(AttributeSet::contains(index->local().attribute()))
+ ++entries;
+
+ selected_ = new uint32_t[entries];
+ built_ = true;
+
+ entries = 0;
+ for(const_iterator index = indexset.begin(); index != end; ++index)
+ if(AttributeSet::contains(index->local().attribute()))
+ selected_[entries++]= index->local().local();
+
+ size_=entries;
+ built_=true;
+ }
+
+ template<typename TS, typename TG, typename TL, int N>
+ uint32_t* Selection<TS,TG,TL,N>::begin() const
+ {
+ return selected_;
+ }
+
+ template<typename TS, typename TG, typename TL, int N>
+ uint32_t* Selection<TS,TG,TL,N>::end() const
+ {
+ return selected_+size_;
+ }
+
+ template<typename TS, typename TG, typename TL, int N>
+ inline void Selection<TS,TG,TL,N>::free()
+ {
+ delete[] selected_;
+ size_=0;
+ built_=false;
+ }
+
+ template<typename TS, typename TG, typename TL, int N>
+ inline Selection<TS,TG,TL,N>::~Selection()
+ {
+ if(built_)
+ free();
+ }
+
+ template<typename TS, typename TG, typename TL, int N>
+ SelectionIterator<TS,TG,TL,N> UncachedSelection<TS,TG,TL,N>::begin() const
+ {
+ return SelectionIterator<TS,TG,TL,N>(indexSet_->begin(),
+ indexSet_->end());
+ }
+
+ template<typename TS, typename TG, typename TL, int N>
+ SelectionIterator<TS,TG,TL,N> UncachedSelection<TS,TG,TL,N>::end() const
+ {
+ return SelectionIterator<TS,TG,TL,N>(indexSet_->end(),
+ indexSet_->end());
+ }
+ template<typename TS, typename TG, typename TL, int N>
+ void UncachedSelection<TS,TG,TL,N>::setIndexSet(const ParallelIndexSet& indexset)
+ {
+ indexSet_ = &indexset;
+ }
+
+ /** @} */
+
+
+}
+#endif
--- /dev/null
+Makefile.in
+Makefile
+.deps
+indexsettest
+indicestest
+selectiontest
+syncertest
--- /dev/null
+set(MPITESTPROGS indicestest indexsettest syncertest selectiontest variablesizecommunicatortest)
+
+add_directory_test_target(_test_target)
+# We do not want want to build the tests during make all,
+# but just build them on demand
+add_dependencies(${_test_target} ${MPITESTPROGS})
+
+add_executable("indexsettest" indexsettest.cc)
+target_link_libraries("indexsettest" "dunecommon" ${CMAKE_THREAD_LIBS_INIT} ${})
+
+include(DuneMPI)
+add_executable("indicestest" indicestest.cc)
+target_link_libraries("indicestest" "dunecommon")
+add_dune_mpi_flags(indicestest)
+
+add_executable("selectiontest" selectiontest.cc)
+target_link_libraries("selectiontest" "dunecommon")
+add_dune_mpi_flags(selectiontest)
+
+add_executable("syncertest" syncertest.cc)
+target_link_libraries("syncertest" "dunecommon")
+add_dune_mpi_flags(syncertest)
+
+add_executable("variablesizecommunicatortest" variablesizecommunicatortest.cc)
+target_link_libraries("variablesizecommunicatortest" "dunecommon")
+add_dune_mpi_flags(variablesizecommunicatortest)
+
+add_test(indexsettest indexsettest)
+add_test(selectiontest selectiontest)
+add_test(indicestest indicestest)
+add_test(syncertest syncertest)
+add_test(variablesizecommunicatortest variablesizecommunicatortest)
--- /dev/null
+# $Id$
+
+MPITESTS = indicestest \
+ indexsettest \
+ syncertest \
+ selectiontest \
+ variablesizecommunicatortest
+
+# which tests where program to build and run are equal
+NORMALTESTS =
+
+# list of tests to run (indicestest is special case)
+TESTS = $(NORMALTESTS) $(MPITESTS)
+
+# programs just to build when "make check" is used
+check_PROGRAMS = $(NORMALTESTS) $(MPITESTS)
+
+# define the programs
+indicestest_SOURCES = indicestest.cc
+indicestest_CPPFLAGS = $(AM_CPPFLAGS) \
+ $(DUNEMPICPPFLAGS)
+indicestest_LDFLAGS = $(AM_LDFLAGS) \
+ $(DUNEMPILDFLAGS)
+indicestest_LDADD = \
+ $(DUNEMPILIBS) \
+ $(LDADD)
+
+selectiontest_SOURCES = selectiontest.cc
+selectiontest_CPPFLAGS = $(AM_CPPFLAGS) \
+ $(DUNEMPICPPFLAGS)
+selectiontest_LDFLAGS = $(AM_LDFLAGS) \
+ $(DUNEMPILDFLAGS)
+selectiontest_LDADD = \
+ $(DUNEMPILIBS) \
+ $(LDADD)
+
+indexsettest_SOURCES = indexsettest.cc
+
+syncertest_SOURCES = syncertest.cc
+syncertest_CPPFLAGS = $(AM_CPPFLAGS) \
+ $(DUNEMPICPPFLAGS) \
+ $(DUNE_COMMON_CPPFLAGS)
+syncertest_LDFLAGS = $(AM_LDFLAGS) \
+ $(DUNEMPILDFLAGS) \
+ $(DUNE_COMMON_LDFLAGS)
+syncertest_LDADD = \
+ $(DUNE_COMMON_LDFLAGS) $(DUNE_COMMON_LIBS) \
+ $(DUNEMPILIBS) \
+ $(LDADD)
+
+
+variablesizecommunicatortest_SOURCES = variablesizecommunicatortest.cc
+variablesizecommunicatortest_CPPFLAGS = $(AM_CPPFLAGS) \
+ $(DUNEMPICPPFLAGS) \
+ $(DUNE_COMMON_CPPFLAGS)
+variablesizecommunicatortest_LDFLAGS = $(AM_LDFLAGS) \
+ $(DUNEMPILDFLAGS) \
+ $(DUNE_COMMON_LDFLAGS)
+variablesizecommunicatortest_LDADD = \
+ $(DUNE_COMMON_LDFLAGS) $(DUNE_COMMON_LIBS) \
+ $(DUNEMPILIBS) \
+ $(LDADD)
+
+include $(top_srcdir)/am/global-rules
+
+EXTRA_DIST = CMakeLists.txt
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <cstdlib>
+#include <iostream>
+#include <ostream>
+
+#include <dune/common/parallel/indexset.hh>
+#include <dune/common/parallel/localindex.hh>
+
+int testDeleteIndices()
+{
+ Dune::ParallelIndexSet<int,Dune::LocalIndex,15> indexSet;
+ Dune::ParallelIndexSet<int,Dune::LocalIndex,25> indexSet1;
+
+ indexSet.beginResize();
+ indexSet1.beginResize();
+
+ for(int i=0; i< 10; i++) {
+ indexSet.add(i, Dune::LocalIndex (i));
+ indexSet1.add(i, Dune::LocalIndex (i));
+ }
+
+ indexSet.endResize();
+ indexSet1.endResize();
+
+ typedef Dune::ParallelIndexSet<int,Dune::LocalIndex,15>::iterator
+ Iterator;
+
+ Iterator entry = indexSet.begin();
+ indexSet.beginResize();
+
+ for(int i=0; i < 5; i++)
+ ++entry;
+
+ indexSet.markAsDeleted(entry);
+
+ indexSet.endResize();
+
+ std::cout<<"Unchanged: "<<indexSet1<<std::endl;
+ std::cout<<"Deleted: "<<indexSet<<std::endl;
+
+ Iterator end = indexSet.end();
+ int i=0, ret=0;
+
+ for(entry = indexSet.begin(); entry != end; ++entry,++i)
+ if(entry->global()==5) {
+ std::cerr<<"Entry was not deleted!"<<std::endl;
+ ret++;
+ }
+
+ if(i>9) {
+ std::cerr<<"Number of entries not correct!"<<std::endl;
+ ret++;
+ }
+
+ Dune::ParallelIndexSet<int,Dune::LocalIndex,25>::iterator iter=indexSet1.begin();
+
+ // Test whether the local indices changed
+ for(entry = indexSet.begin(); entry != end; ++entry) {
+ while(iter->global() < entry->global())
+ iter++;
+ if(iter->global() != entry->global()) {
+ std::cerr <<" Global indices do not match!"<<std::endl;
+ ++ret;
+ }
+ if(iter->local() != entry->local()) {
+ std::cerr <<" Local indices do not match!"<<std::endl;
+ ++ret;
+ }
+ }
+
+ return ret;
+}
+
+int main(int, char **)
+{
+ std::exit(testDeleteIndices());
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#include "config.h"
+#include <dune/common/parallel/indexset.hh>
+#include <dune/common/parallel/communicator.hh>
+#include <dune/common/parallel/remoteindices.hh>
+#include <dune/common/enumset.hh>
+#include <algorithm>
+#include <iostream>
+
+#if HAVE_MPI
+#include "mpi.h"
+
+enum GridFlags {
+ owner, overlap, border
+};
+
+class Array;
+
+std::ostream& operator<<(std::ostream& os, const Array& a);
+
+class Array
+{
+ friend std::ostream& operator<<(std::ostream& os, const Array& a);
+public:
+ typedef double value_type;
+ Array() : vals_(0), size_(0)
+ {}
+
+ Array(int size) : size_(size)
+ {
+ vals_ = new double[size];
+ }
+
+ void build(int size)
+ {
+ vals_ = new double[size];
+ size_ = size;
+ }
+
+ Array& operator+=(double d)
+ {
+ for(int i=0; i < size_; i++)
+ vals_[i]+=d;
+ return *this;
+ }
+
+ ~Array()
+ {
+ if(vals_!=0)
+ delete[] vals_;
+ }
+
+ const double& operator[](int i) const
+ {
+ return vals_[i];
+ }
+
+ double& operator[](int i)
+ {
+ return vals_[i];
+ }
+private:
+ Array(const Array&)
+ {}
+ double *vals_;
+ int size_;
+};
+
+struct ArrayGatherScatter
+{
+ static double gather(const Array& a, int i);
+
+ static void scatter(Array& a, double v, int i);
+
+};
+
+
+inline double ArrayGatherScatter::gather(const Array& a, int i)
+{
+ return a[i];
+}
+
+inline void ArrayGatherScatter::scatter(Array& a, double v, int i)
+{
+ a[i]=v;
+
+}
+
+std::ostream& operator<<(std::ostream& os, const Array& a)
+{
+ if(a.size_>0)
+ os<< "{ "<<a.vals_[0];
+
+ for(int i=1; i<a.size_; i++)
+ os <<", "<< a.vals_[i];
+
+ os << " }";
+ return os;
+}
+
+void testIndices(MPI_Comm comm)
+{
+ //using namespace Dune;
+
+ // The global grid size
+ const int Nx = 20;
+ const int Ny = 2;
+
+ // Process configuration
+ int procs, rank, master=0;
+ MPI_Comm_size(comm, &procs);
+ MPI_Comm_rank(comm, &rank);
+
+ // shift the ranks
+ //rank = (rank + 1) % procs;
+ //master= (master+1) %procs;
+
+ // The local grid
+ int nx = Nx/procs;
+ // distributed indexset
+ // typedef ParallelLocalIndex<GridFlags> LocalIndexType;
+
+ typedef Dune::ParallelIndexSet<int,Dune::ParallelLocalIndex<GridFlags>,45> ParallelIndexSet;
+
+ ParallelIndexSet distIndexSet;
+ // global indexset
+ ParallelIndexSet globalIndexSet;
+
+ // Set up the indexsets.
+ int start = std::max(rank*nx-1,0);
+ int end = std::min((rank + 1) * nx+1, Nx);
+
+ distIndexSet.beginResize();
+
+ int localIndex=0;
+ int size = Ny*(end-start);
+ Array distArray(size);
+ Array* globalArray;
+ int index=0;
+
+ std::cout<<rank<<": Nx="<<Nx<<" Ny="<<Ny<<" size="<<size<<std::endl;
+
+ for(int j=0; j<Ny; j++)
+ for(int i=start; i<end; i++) {
+ bool isPublic = (i<=start+1)||(i>=end-2);
+ GridFlags flag = owner;
+ if((i==start && i!=0)||(i==end-1 && i!=Nx-1)) {
+ distArray[index++]=-(i+j*Nx+rank*Nx*Ny);
+ flag = overlap;
+ }else
+ distArray[index++]=i+j*Nx+rank*Nx*Ny;
+
+ distIndexSet.add(i+j*Nx, Dune::ParallelLocalIndex<GridFlags> (localIndex++,flag,isPublic));
+ }
+
+ distIndexSet.endResize();
+
+ if(rank==master) {
+ // build global indexset on first process
+ globalIndexSet.beginResize();
+ globalArray=new Array(Nx*Ny);
+ int k=0;
+ for(int j=0; j<Ny; j++)
+ for(int i=0; i<Nx; i++) {
+ globalIndexSet.add(i+j*Nx, Dune::ParallelLocalIndex<GridFlags> (i+j*Nx,owner,false));
+ globalArray->operator[](i+j*Nx)=-(i+j*Nx);
+ k++;
+
+ }
+
+ globalIndexSet.endResize();
+ }else
+ globalArray=new Array(0);
+
+ typedef Dune::RemoteIndices<ParallelIndexSet> RemoteIndices;
+
+ RemoteIndices accuIndices(distIndexSet, globalIndexSet, comm);
+ RemoteIndices overlapIndices(distIndexSet, distIndexSet, comm);
+ accuIndices.rebuild<true>();
+ overlapIndices.rebuild<false>();
+
+ Dune::DatatypeCommunicator<ParallelIndexSet> accumulator, overlapExchanger;
+
+ Dune::EnumItem<GridFlags,owner> sourceFlags;
+ Dune::Combine<Dune::EnumItem<GridFlags,overlap>,Dune::EnumItem<GridFlags,owner>,GridFlags> destFlags;
+
+ accumulator.build(accuIndices, sourceFlags, distArray, destFlags, *globalArray);
+
+ overlapExchanger.build(overlapIndices, Dune::EnumItem<GridFlags,owner>(), distArray, Dune::EnumItem<GridFlags,overlap>(), distArray);
+
+ std::cout<< rank<<": before forward distArray="<< distArray<<std::endl;
+
+ // Exchange the overlap
+ overlapExchanger.forward();
+
+ std::cout<<rank<<": overlap exchanged distArray"<< distArray<<std::endl;
+
+ if(rank==master)
+ std::cout<<": before forward globalArray="<< *globalArray<<std::endl;
+
+ accumulator.forward();
+
+
+ if(rank==master) {
+ std::cout<<"after forward global: "<<*globalArray<<std::endl;
+ *globalArray+=1;
+ std::cout<<" added one: globalArray="<<*globalArray<<std::endl;
+ }
+
+ accumulator.backward();
+ std::cout<< rank<<": after backward distArray"<< distArray<<std::endl;
+
+
+ // Exchange the overlap
+ overlapExchanger.forward();
+
+ std::cout<<rank<<": overlap exchanged distArray"<< distArray<<std::endl;
+
+ //std::cout << rank<<": source and dest are the same:"<<std::endl;
+ //std::cout << remote<<std::endl<<std::flush;
+ if(rank==master)
+ delete globalArray;
+}
+
+
+template<int NX, int NY, typename TG, typename TA>
+void setupDistributed(Array& distArray, Dune::ParallelIndexSet<TG,Dune::ParallelLocalIndex<TA> >& distIndexSet,
+ int rank, int procs)
+{
+ // The local grid
+ int nx = NX/procs;
+ int mod = NX%procs;
+
+ // Set up the indexsets.
+ int start, end;
+ int ostart, oend;
+
+ if(rank<mod) {
+ start = rank * (nx + 1);
+ end = start + (nx + 1);
+ }else{
+ start = mod + rank * nx;
+ end = start + nx;
+ }
+
+ if(rank>0)
+ ostart = start - 1;
+ else
+ ostart = start;
+
+ if(rank<procs-1)
+ oend = end+1;
+ else
+ oend = end;
+
+ distIndexSet.beginResize();
+
+ int localIndex=0;
+ int size = NY*(oend-ostart);
+
+ distArray.build(size);
+
+ for(int j=0; j<NY; j++)
+ for(int i=ostart; i<oend; i++) {
+ bool isPublic = (i<=start+1)||(i>=end-1);
+ GridFlags flag = owner;
+ if((i<start || i>=end)) {
+ distArray[localIndex]=-(i+j*NX+rank*NX*NY);
+ flag = overlap;
+ }else
+ distArray[localIndex]=i+j*NX+rank*NX*NY;
+
+ distIndexSet.add(i+j*NX, Dune::ParallelLocalIndex<GridFlags> (localIndex++,flag,isPublic));
+ }
+
+ distIndexSet.endResize();
+
+
+}
+
+template<int NX,int NY, typename TG, typename TA>
+void setupGlobal(Array& globalArray, Dune::ParallelIndexSet<TG,Dune::ParallelLocalIndex<TA> >& globalIndexSet)
+{
+ // build global indexset on first process
+ globalIndexSet.beginResize();
+ globalArray.build(NX*NY);
+ int k=0;
+ for(int j=0; j<NY; j++)
+ for(int i=0; i<NX; i++) {
+ globalIndexSet.add(i+j*NX, Dune::ParallelLocalIndex<GridFlags> (i+j*NX,owner,false));
+ globalArray[i+j*NX]=-(i+j*NX);
+ k++;
+
+ }
+
+ globalIndexSet.endResize();
+}
+
+void testIndicesBuffered(MPI_Comm comm)
+{
+ //using namespace Dune;
+
+ // The global grid size
+ const int Nx = 8;
+ const int Ny = 1;
+
+ // Process configuration
+ int procs, rank, master=0;
+ MPI_Comm_size(comm, &procs);
+ MPI_Comm_rank(comm, &rank);
+
+ typedef Dune::ParallelIndexSet<int,Dune::ParallelLocalIndex<GridFlags> > ParallelIndexSet;
+
+ ParallelIndexSet distIndexSet;
+ // global indexset
+ ParallelIndexSet globalIndexSet;
+
+ Array distArray;
+ Array globalArray;
+
+ setupDistributed<Nx,Ny>(distArray, distIndexSet, rank, procs);
+
+
+ if(rank==master) {
+ setupGlobal<Nx,Ny>(globalArray, globalIndexSet);
+ }
+
+ typedef Dune::RemoteIndices<ParallelIndexSet> RemoteIndices;
+
+ RemoteIndices accuIndices(distIndexSet, globalIndexSet, comm);
+
+ accuIndices.rebuild<true>();
+ std::cout<<"dist "<<rank<<": "<<distIndexSet<<std::endl;
+ std::cout<<"global "<<rank<<": "<<globalIndexSet<<std::endl;
+ std::cout << accuIndices<<std::endl;
+ std::cout <<" end remote indices"<<std::endl;
+
+ RemoteIndices overlapIndices(distIndexSet, distIndexSet, comm);
+ overlapIndices.rebuild<false>();
+
+ Dune::Interface accuInterface;
+ Dune::Interface overlapInterface;
+ Dune::EnumItem<GridFlags,owner> sourceFlags;
+ Dune::Combine<Dune::EnumItem<GridFlags,overlap>,Dune::EnumItem<GridFlags,owner>,GridFlags> destFlags;
+ // Dune::Bool2Type<true> flag;
+
+ accuInterface.build(accuIndices, sourceFlags, destFlags);
+ overlapInterface.build(overlapIndices, Dune::EnumItem<GridFlags,owner>(),
+ Dune::EnumItem<GridFlags,overlap>());
+ overlapInterface.print();
+ accuInterface.print();
+
+ //accuInterface.print();
+
+ Dune::BufferedCommunicator accumulator, overlapExchanger;
+
+ accumulator.build<Array>(accuInterface);
+
+ overlapExchanger.build<Array>(overlapInterface);
+
+ std::cout<< rank<<": before forward distArray="<< distArray<<std::endl;
+
+ // Exchange the overlap
+ overlapExchanger.forward<ArrayGatherScatter>(distArray, distArray);
+
+ std::cout<<rank<<": overlap exchanged distArray"<< distArray<<std::endl;
+
+ if(rank==master)
+ std::cout<<": before forward globalArray="<< globalArray<<std::endl;
+
+ accumulator.forward<ArrayGatherScatter>(distArray, globalArray);
+
+
+ if(rank==master) {
+ std::cout<<"after forward global: "<<globalArray<<std::endl;
+ globalArray+=1;
+ std::cout<<" added one: globalArray="<<globalArray<<std::endl;
+ }
+
+ accumulator.backward<ArrayGatherScatter>(distArray, globalArray);
+ std::cout<< rank<<": after backward distArray"<< distArray<<std::endl;
+
+
+ // Exchange the overlap
+ overlapExchanger.forward<ArrayGatherScatter>(distArray);
+
+ std::cout<<rank<<": overlap exchanged distArray"<< distArray<<std::endl;
+
+ //std::cout << rank<<": source and dest are the same:"<<std::endl;
+ //std::cout << remote<<std::endl<<std::flush;
+}
+
+
+void testRedistributeIndices(MPI_Comm comm)
+{
+ using namespace Dune;
+
+ // The global grid size
+ const int Nx = 20;
+ const int Ny = 2;
+
+ // Process configuration
+ int procs, rank;
+ MPI_Comm_size(comm, &procs);
+ MPI_Comm_rank(comm, &rank);
+
+ // The local grid
+ int nx = Nx/procs;
+ // distributed indexset
+
+ typedef ParallelIndexSet<int,ParallelLocalIndex<GridFlags> > ParallelIndexSet;
+ ParallelIndexSet sendIndexSet;
+ // global indexset
+ ParallelIndexSet receiveIndexSet;
+
+ Array array, redistributedArray;
+
+ // Set up the indexsets.
+ {
+
+ int start = std::max(rank*nx-1,0);
+ int end = std::min((rank + 1) * nx+1, Nx);
+
+ sendIndexSet.beginResize();
+
+
+ array.build(Ny*(end-start));
+
+ for(int j=0, localIndex=0; j<Ny; j++)
+ for(int i=start; i<end; i++, localIndex++) {
+ bool isPublic = (i<=start+1)||(i>=end-2);
+ GridFlags flag = owner;
+
+ if((i==start && i!=0)||(i==end-1 && i!=Nx-1))
+ flag = overlap;
+
+ sendIndexSet.add(i+j*Nx, ParallelLocalIndex<GridFlags> (localIndex,flag,isPublic));
+ array[localIndex]=i+j*Nx+rank*Nx*Ny;
+ }
+
+ sendIndexSet.endResize();
+ }
+ {
+ int newrank = (rank + 1) % procs;
+
+ int start = std::max(newrank*nx-1,0);
+ int end = std::min((newrank + 1) * nx+1, Nx);
+
+ std::cout<<rank<<": "<<newrank<<" start="<<start<<" end"<<end<<std::endl;
+
+ redistributedArray.build(Ny*(end-start));
+
+ receiveIndexSet.beginResize();
+
+ for(int j=0, localIndex=0; j<Ny; j++)
+ for(int i=start; i<end; i++, localIndex++) {
+ bool isPublic = (i<=start+1)||(i>=end-2);
+ GridFlags flag = owner;
+
+ if((i==start && i!=0)||(i==end-1 && i!=Nx-1))
+ flag = overlap;
+
+ receiveIndexSet.add(i+j*Nx, ParallelLocalIndex<GridFlags> (localIndex,flag,isPublic));
+ redistributedArray[localIndex]=-1;
+ }
+
+ receiveIndexSet.endResize();
+ }
+
+
+ std::cout<< rank<<": distributed and global index set!"<<std::endl<<std::flush;
+ typedef RemoteIndices<ParallelIndexSet> RemoteIndices;
+
+ RemoteIndices redistributeIndices(sendIndexSet,
+ receiveIndexSet, comm);
+ RemoteIndices overlapIndices(receiveIndexSet, receiveIndexSet, comm);
+
+ redistributeIndices.rebuild<true>();
+ overlapIndices.rebuild<false>();
+
+ DatatypeCommunicator<ParallelIndexSet> redistribute, overlapComm;
+ EnumItem<GridFlags,owner> fowner;
+ EnumItem<GridFlags,overlap> foverlap;
+
+ redistribute.build(redistributeIndices, fowner, array, fowner, redistributedArray);
+
+ overlapComm.build(overlapIndices, fowner, redistributedArray, foverlap, redistributedArray);
+ std::cout<<rank<<": initial array: "<<array<<std::endl;
+
+ redistribute.forward();
+
+ std::cout<<rank<<": redistributed array: "<<redistributedArray<<std::endl;
+
+ overlapComm.forward();
+
+ std::cout<<rank<<": redistributed array with overlap communicated: "<<redistributedArray<<std::endl;
+}
+
+void testRedistributeIndicesBuffered(MPI_Comm comm)
+{
+ using namespace Dune;
+
+ // The global grid size
+ const int Nx = 20;
+ const int Ny = 2;
+
+ // Process configuration
+ int procs, rank;
+ MPI_Comm_size(comm, &procs);
+ MPI_Comm_rank(comm, &rank);
+
+ // The local grid
+ int nx = Nx/procs;
+ // distributed indexset
+
+ typedef ParallelIndexSet<int,ParallelLocalIndex<GridFlags> > ParallelIndexSet;
+ ParallelIndexSet sendIndexSet;
+ // global indexset
+ ParallelIndexSet receiveIndexSet;
+
+ Array array, redistributedArray;
+
+ std::vector<int> neighbours;
+
+ // Set up the indexsets.
+ {
+
+ int start = std::max(rank*nx-1,0);
+ int end = std::min((rank + 1) * nx+1, Nx);
+
+ neighbours.reserve(2);
+
+ if(rank>0) neighbours.push_back(rank-1);
+ if(rank<procs-1) neighbours.push_back(rank+1);
+
+ sendIndexSet.beginResize();
+
+
+ array.build(Ny*(end-start));
+
+ for(int j=0, localIndex=0; j<Ny; j++)
+ for(int i=start; i<end; i++, localIndex++) {
+ bool isPublic = (i<=start+1)||(i>=end-2);
+ GridFlags flag = owner;
+
+ if((i==start && i!=0)||(i==end-1 && i!=Nx-1))
+ flag = overlap;
+
+ sendIndexSet.add(i+j*Nx, ParallelLocalIndex<GridFlags> (localIndex,flag,isPublic));
+ array[localIndex]=i+j*Nx; //+rank*Nx*Ny;
+ if(flag==overlap)
+ array[localIndex]=-array[localIndex];
+ }
+
+ sendIndexSet.endResize();
+ }
+ {
+ int newrank = (rank + 1) % procs;
+
+ int start = std::max(newrank*nx-1,0);
+ int end = std::min((newrank + 1) * nx+1, Nx);
+
+ std::cout<<rank<<": "<<newrank<<" start="<<start<<" end"<<end<<std::endl;
+
+ redistributedArray.build(Ny*(end-start));
+
+ receiveIndexSet.beginResize();
+
+ for(int j=0, localIndex=0; j<Ny; j++)
+ for(int i=start; i<end; i++, localIndex++) {
+ bool isPublic = (i<=start+1)||(i>=end-2);
+ GridFlags flag = owner;
+
+ if((i==start && i!=0)||(i==end-1 && i!=Nx-1))
+ flag = overlap;
+
+ receiveIndexSet.add(i+j*Nx, ParallelLocalIndex<GridFlags> (localIndex,flag,isPublic));
+ redistributedArray[localIndex]=-1;
+ }
+
+ receiveIndexSet.endResize();
+ }
+
+
+ std::cout<< rank<<": distributed and global index set!"<<std::endl<<std::flush;
+
+ typedef RemoteIndices<ParallelIndexSet> RemoteIndices;
+ RemoteIndices redistributeIndices(sendIndexSet,
+ receiveIndexSet, comm);
+ RemoteIndices overlapIndices(receiveIndexSet, receiveIndexSet, comm);
+ RemoteIndices sendIndices(sendIndexSet,
+ sendIndexSet, comm, neighbours);
+ RemoteIndices sendIndices1(sendIndexSet,
+ sendIndexSet, comm);
+ overlapIndices.rebuild<false>();
+ redistributeIndices.rebuild<true>();
+ sendIndices.rebuild<true>();
+ sendIndices1.rebuild<true>();
+
+ if(rank==0)
+ std::cout<<sendIndices<<std::endl<<sendIndices1<<std::endl;
+
+ assert(sendIndices==sendIndices1);
+
+ std::cout<<redistributeIndices<<std::endl;
+
+ Interface redistributeInterface, overlapInterface;
+ EnumItem<GridFlags,owner> fowner;
+ EnumItem<GridFlags,overlap> foverlap;
+
+ redistributeInterface.build(redistributeIndices, fowner, fowner);
+ overlapInterface.build(overlapIndices, fowner, foverlap);
+
+ BufferedCommunicator redistribute;
+ BufferedCommunicator overlapComm;
+
+ redistribute.build(array, redistributedArray, redistributeInterface);
+ overlapComm.build<Array>(overlapInterface);
+
+ std::cout<<rank<<": initial array: "<<array<<std::endl;
+
+ redistribute.forward<ArrayGatherScatter>(array, redistributedArray);
+
+ std::cout<<rank<<": redistributed array: "<<redistributedArray<<std::endl;
+
+ redistributedArray +=1;
+
+ std::cout<<rank<<": redistributed array (added one): "<<redistributedArray<<std::endl;
+
+ overlapComm.forward<ArrayGatherScatter>(redistributedArray);
+
+ std::cout<<rank<<": redistributed array with overlap communicated: "<<redistributedArray<<std::endl;
+
+ redistribute.backward<ArrayGatherScatter>(array, redistributedArray);
+
+ std::cout<<rank<<": final array: "<<array<<std::endl;
+
+ redistribute.forward<ArrayGatherScatter>(array, redistributedArray);
+
+ std::cout<<rank<<": final array with overlap communicated: "<<array<<std::endl;
+}
+
+
+/**
+ * @brief MPI Error.
+ * Thrown when an mpi error occurs.
+ */
+class MPIError {
+public:
+ /** @brief Constructor. */
+ MPIError(std::string s, int e) : errorstring(s), errorcode(e){}
+ /** @brief The error string. */
+ std::string errorstring;
+ /** @brief The mpi error code. */
+ int errorcode;
+};
+
+void MPI_err_handler(MPI_Comm *comm, int *err_code, ...){
+ DUNE_UNUSED_PARAMETER(comm);
+ char *err_string=new char[MPI_MAX_ERROR_STRING];
+ int err_length;
+ MPI_Error_string(*err_code, err_string, &err_length);
+ std::string s(err_string, err_length);
+ int rank;
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+ std::cerr << rank<<": An MPI Error ocurred:"<<std::endl<<s<<std::endl;
+ delete[] err_string;
+ throw MPIError(s, *err_code);
+}
+#endif // HAVE_MPI
+
+int main(int argc, char **argv)
+{
+#if HAVE_MPI
+ MPI_Init(&argc, &argv);
+ MPI_Errhandler handler;
+ MPI_Errhandler_create(MPI_err_handler, &handler);
+ MPI_Errhandler_set(MPI_COMM_WORLD, handler);
+ int rank;
+ int size;
+ const int firstRank=2;
+ MPI_Comm_size(MPI_COMM_WORLD, &size);
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+ MPI_Comm comm;
+ int key = rank;
+
+ if(size>firstRank) {
+ if(rank==0)
+ key = firstRank;
+ if(rank==firstRank)
+ key=0;
+ }
+
+ MPI_Comm_split(MPI_COMM_WORLD, 0, key, &comm);
+
+#ifdef DEBUG
+ bool wait=1;
+ while(size>1 && wait) ;
+#endif
+
+ // testIndices(comm);
+ testIndicesBuffered(comm);
+
+ if(rank==0)
+ std::cout<<std::endl<<"Redistributing bla!"<<std::endl<<std::endl;
+ MPI_Barrier(comm);
+
+
+ // testRedistributeIndices(comm);
+ testRedistributeIndicesBuffered(comm);
+ MPI_Comm_free(&comm);
+ MPI_Finalize();
+
+ return 0;
+#else
+ return 77;
+#endif
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#include "config.h"
+#include <iostream>
+#include <dune/common/timer.hh>
+#include <dune/common/enumset.hh>
+#include <dune/common/parallel/remoteindices.hh>
+#include <dune/common/parallel/selection.hh>
+
+enum GridFlags {
+ owner, overlap, border
+};
+
+template<class T>
+int meassure(const T& selection)
+{
+ /*
+ return meassure<1>(selection);
+ }
+
+ template<int LOOPS, class T>
+ int meassure(const T& selection)
+ {*/
+ typedef typename T::const_iterator iterator;
+
+ const iterator end = selection.end();
+
+ int count=0;
+ Dune::Timer timer;
+ timer.reset();
+ for(int i=0; i<10; i++)
+ for(iterator iter = selection.begin(); iter != end; ++iter)
+ count+=*iter;
+
+ std::cout<<" took "<< timer.elapsed()<<" seconds"<<std::endl;
+
+ return count;
+}
+
+template<int SIZE>
+void test()
+{
+ const int Nx = SIZE;
+ const int Ny = SIZE;
+
+ // Process configuration
+ const int ALSIZE=55;
+
+ Dune::ParallelIndexSet<int,Dune::ParallelLocalIndex<GridFlags>,ALSIZE> distIndexSet;
+
+ distIndexSet.beginResize();
+
+ for(int y=0, i=0; y < Ny; y++)
+ for(int x=0; x < Nx; x++, i++) {
+ GridFlags flag = owner;
+ if(x==0 || x == Nx-1 || y ==0 || y==Ny-1)
+ flag = overlap;
+
+ distIndexSet.add(i, Dune::ParallelLocalIndex<GridFlags> (i, flag, true));
+ }
+
+ distIndexSet.endResize();
+
+ Dune::UncachedSelection<Dune::EnumItem<GridFlags,owner>,int,Dune::ParallelLocalIndex<GridFlags>,ALSIZE>
+ ownerUncached(distIndexSet);
+
+ Dune::Selection<Dune::EnumItem<GridFlags,owner>,int,Dune::ParallelLocalIndex<GridFlags>,ALSIZE>
+ ownerCached(distIndexSet);
+
+ Dune::UncachedSelection<Dune::EnumItem<GridFlags,overlap>,int,Dune::ParallelLocalIndex<GridFlags>,ALSIZE>
+ overlapUncached(distIndexSet);
+
+ Dune::Selection<Dune::EnumItem<GridFlags,overlap>,int,Dune::ParallelLocalIndex<GridFlags>,ALSIZE>
+ overlapCached(distIndexSet);
+
+ int count=0;
+
+ std::cout<<" Owner selection uncached:";
+ count+=meassure(ownerUncached);
+ std::cout<<" Owner selection cached:";
+ count+=meassure(ownerCached);
+ std::cout<<" Overlap selection uncached:";
+ count+=meassure(overlapUncached);
+ std::cout<<" Overlap selection cached:";
+ count+=meassure(overlapCached);
+ std::cout<<count<<std::endl;
+}
+
+int main()
+{
+ test<1000>();
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#include "config.h"
+
+#if HAVE_MPI
+
+#include <dune/common/parallel/indicessyncer.hh>
+#include <dune/common/sllist.hh>
+#include <string>
+#include <iostream>
+
+enum GridFlags {
+ owner, overlap, border
+};
+
+template<typename T>
+void deleteOverlapEntries(T& indices,
+ Dune::RemoteIndices<T>& remoteIndices)
+{
+ typedef typename T::iterator IndexIterator;
+ typedef typename T::GlobalIndex GlobalIndex;
+ typedef typename T::LocalIndex::Attribute Attribute;
+ typedef Dune::RemoteIndices<T> RemoteIndices;
+ typedef typename RemoteIndices::RemoteIndexList::ModifyIterator RemoteModifier;
+ typedef typename RemoteIndices::RemoteIndexList::const_iterator RemoteIterator;
+ typedef Dune::SLList<std::pair<GlobalIndex,Attribute>, typename RemoteIndices::RemoteIndexList::Allocator> GlobalList;
+ typedef typename GlobalList::ModifyIterator GlobalModifier;
+ typedef Dune::tuple<RemoteModifier,GlobalModifier,const RemoteIterator,const typename GlobalList::const_iterator,
+ const GlobalList*, const typename RemoteIndices::RemoteIndexList*> IteratorTuple;
+ typedef std::map<int,IteratorTuple> IteratorMap;
+ typedef typename RemoteIndices::const_iterator RemoteMapIterator;
+
+ int rank;
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+ std::map<int,GlobalList> globalLists;
+
+ IteratorMap iterators;
+ RemoteMapIterator rmEnd = remoteIndices.end();
+
+ for(RemoteMapIterator remote = remoteIndices.begin();
+ remote != rmEnd; ++remote) {
+ // Initialize global indices
+ GlobalList& gList=globalLists[remote->first];
+ const RemoteIterator rend = remote->second.first->end();
+
+ for(RemoteIterator index= remote->second.first->begin();
+ index != rend; ++index)
+ gList.push_back(std::make_pair(index->localIndexPair().global(),
+ index->localIndexPair().local().attribute()));
+
+ assert(gList.size()==remote->second.first->size());
+ std::cout << "Size of remote indices is "<<gList.size()<<std::endl;
+
+ iterators.insert(std::make_pair(remote->first,
+ IteratorTuple(remote->second.first->beginModify(),
+ gList.beginModify(),
+ rend,
+ gList.end(),
+ &gList,
+ remote->second.first)));
+ }
+
+ indices.beginResize();
+
+ const IndexIterator endIndex = indices.end();
+ for(IndexIterator index = indices.begin(); index != endIndex; ++index) {
+ if(index->local().attribute()==overlap) {
+ std::cout << rank<<": Deleting "<<*index<<std::endl;
+
+ indices.markAsDeleted(index);
+
+ // Delete corresponding indices in all remote index lists.
+ typedef typename IteratorMap::iterator iterator;
+ iterator end = iterators.end();
+
+ for(iterator remote = iterators.begin(); remote != end; ++remote) {
+
+ // Search for the index
+ while(Dune::get<0>(remote->second) != Dune::get<2>(remote->second)
+ && *(Dune::get<1>(remote->second)) < *index) {
+ // increment all iterators
+ ++(Dune::get<0>(remote->second));
+ ++(Dune::get<1>(remote->second));
+ if(Dune::get<0>(remote->second)!=Dune::get<2>(remote->second))
+ assert(Dune::get<1>(remote->second)!=Dune::get<3>(remote->second));
+ }
+
+ // Delete the entry if present
+ if(Dune::get<0>(remote->second) != Dune::get<2>(remote->second)) {
+ assert(Dune::get<1>(remote->second) != Dune::get<3>(remote->second));
+
+ if(*(Dune::get<1>(remote->second)) == *index) {
+
+ std::cout<<rank<<": Deleting remote "<<
+ Dune::get<1>(remote->second)->first<<", "<<
+ Dune::get<1>(remote->second)->second<<" of process "
+ << remote->first<<std::endl;
+
+ // Delete entries
+ Dune::get<0>(remote->second).remove();
+ Dune::get<1>(remote->second).remove();
+ assert(Dune::get<4>(remote->second)->size()==Dune::get<5>(remote->second)->size());
+ }
+ }
+ }
+ }
+ }
+
+ indices.endResize();
+
+ // Update the pointers to the local index pairs
+ Dune::repairLocalIndexPointers(globalLists, remoteIndices, indices);
+ globalLists.clear();
+}
+
+
+template<typename T>
+bool areEqual(T& indices,
+ Dune::RemoteIndices<T>& remoteIndices,
+ T& oIndices,
+ Dune::RemoteIndices<T>& oRemoteIndices){
+
+ typedef typename T::iterator IndexIterator;
+ typedef Dune::RemoteIndices<T> RemoteIndices;
+ typedef typename RemoteIndices::RemoteIndexList::iterator RemoteIterator;
+
+ IndexIterator iEnd = indices.end();
+ bool ret=true;
+ int rank;
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+ // Test the index sets
+ if(indices.size() != oIndices.size()) {
+ std::cerr<< rank<<": Size of index set is unequal!"<<std::endl;
+ ret= false;
+ }
+ for(IndexIterator index = indices.begin(), oIndex = oIndices.begin();
+ index != iEnd; ++index, ++oIndex) {
+ if( index->global() != oIndex->global()) {
+ std::cerr<<rank<<": Entry for "<<index->global() <<" is missing!"<<std::endl;
+ ret = false;
+ }
+ else if(index->local().attribute() !=oIndex->local().attribute()) {
+ std::cerr<<rank<<": Entry for "<<index->global() <<" has wrong attribute: "<<
+ index->local().attribute()<< "!= "<<oIndex->local().attribute()<<std::endl;
+ ret = false;
+ }
+ }
+
+ // Test the remote index lists
+ typedef typename RemoteIndices::RemoteIndexMap::const_iterator RemoteMapIterator;
+
+ RemoteMapIterator rmEnd = remoteIndices.end();
+
+ for(RemoteMapIterator remote = remoteIndices.begin(),
+ oRemote = oRemoteIndices.begin();
+ remote != rmEnd; ++remote, ++oRemote) {
+ if(oRemote->second.first->size() != remote->second.first->size()) {
+ std::cerr <<rank<<": Size of remote index list for process "<<remote->first
+ <<" does not match!"<<std::endl;
+ ret=false;
+ }
+
+ RemoteIterator rEnd = oRemote->second.first->end();
+ for(RemoteIterator rIndex= remote->second.first->begin(),
+ oRIndex = oRemote->second.first->begin(); oRIndex != rEnd;
+ ++rIndex, ++oRIndex) {
+
+ if(rIndex->localIndexPair().global() != oRIndex->localIndexPair().global()) {
+
+ std::cerr<<rank<<": Remote Entry for "<< rIndex->localIndexPair().global()
+ <<" is missing for process "<<remote->first<<std::endl;
+ ret = false;
+ }
+
+ if(rIndex->attribute() != oRIndex->attribute()) {
+ std::cerr<<rank<<": Attribute for entry "<<rIndex->localIndexPair().global()
+ <<" for process "<< remote->first<<" is wrong: "
+ <<rIndex->attribute()<<" != "<<oRIndex->attribute()<<std::endl;
+ ret = false;
+ }
+ }
+ }
+
+ return ret;
+}
+
+template<typename T>
+void addFakeRemoteIndices(T& indices,
+ T& oIndices,
+ Dune::RemoteIndices<T>& remoteIndices,
+ Dune::RemoteIndices<T>& oRemoteIndices){
+ typedef typename T::iterator IndexIterator;
+ typedef typename T::GlobalIndex GlobalIndex;
+ typedef typename T::LocalIndex::Attribute Attribute;
+ typedef typename Dune::RemoteIndices<T>::RemoteIndexList RemoteIndexList;
+ assert(remoteIndices.neighbours()==0 && oRemoteIndices.neighbours()==0);
+
+ RemoteIndexList* rlist = new RemoteIndexList();
+ RemoteIndexList* orlist = new RemoteIndexList();
+ int added=0;
+ IndexIterator iEnd = indices.end();
+
+ for(IndexIterator index = indices.begin(), oIndex = oIndices.begin();
+ index != iEnd; ++index, ++oIndex) {
+ assert(*index == *oIndex);
+ if(index->local().attribute()==overlap) {
+ added++;
+ rlist->push_back(Dune::RemoteIndex<GlobalIndex,Attribute>(owner,&(*index)));
+ orlist->push_back(Dune::RemoteIndex<GlobalIndex,Attribute>(owner,&(*oIndex)));
+ }
+ }
+
+
+ remoteIndices.remoteIndices_.insert(std::make_pair(1,std::make_pair(rlist,rlist)));
+ oRemoteIndices.remoteIndices_.insert(std::make_pair(1,std::make_pair(orlist,orlist)));
+
+ std::cout<<"Added "<<added<<" fake remote indices!"<<std::endl;
+}
+
+bool testIndicesSyncer()
+{
+ //using namespace Dune;
+
+ // The global grid size
+ const int Nx = 6;
+ const int Ny = 1;
+
+ // Process configuration
+ int procs, rank;
+ MPI_Comm_size(MPI_COMM_WORLD, &procs);
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+ // The local grid
+ int nx = Nx/procs;
+ int first=Nx%procs;
+ // distributed indexset
+ // typedef ParallelLocalIndex<GridFlags> LocalIndexType;
+
+ typedef Dune::ParallelIndexSet<int,Dune::ParallelLocalIndex<GridFlags> > ParallelIndexSet;
+ ParallelIndexSet indexSet, changedIndexSet;
+
+ // Set up the indexsets.
+ int start,end, ostart, oend;
+ if(rank<first) {
+ start = rank*nx+rank;
+ end = rank +rank * nx+nx+1;
+ }else{
+ start = first+rank*nx;
+ end = first +rank*nx +nx;
+ }
+
+ if(rank>0 &&start<Nx)
+ ostart=start-1;
+ else
+ ostart=start;
+
+ if(rank<procs-1 &&end<Nx)
+ oend=end+1;
+ else
+ oend=end;
+
+ std::cout<<rank<<": ostart="<<ostart<<" start="<<start<<" end="<<end<<" oend="<<oend<<std::endl;
+ //return true;
+
+ indexSet.beginResize();
+ changedIndexSet.beginResize();
+
+ int localIndex=0;
+
+ for(int j=0; j<Ny; j++)
+ for(int i=ostart; i<oend; i++) {
+ bool isPublic = (i<start+1)||(i>=end-1);
+ GridFlags flag = owner;
+ if((i==ostart && (i!=0))||(i==end && (i!=Nx-1))) {
+ flag = overlap;
+ }
+
+ indexSet.add(i+j*Nx, Dune::ParallelLocalIndex<GridFlags> (localIndex,flag,isPublic));
+ changedIndexSet.add(i+j*Nx, Dune::ParallelLocalIndex<GridFlags> (localIndex++,flag,isPublic));
+ }
+
+ indexSet.endResize();
+ changedIndexSet.endResize();
+
+ Dune::RemoteIndices<ParallelIndexSet> remoteIndices(indexSet, indexSet, MPI_COMM_WORLD);
+ Dune::RemoteIndices<ParallelIndexSet> changedRemoteIndices(changedIndexSet, changedIndexSet, MPI_COMM_WORLD);
+
+ remoteIndices.rebuild<false>();
+ changedRemoteIndices.rebuild<false>();
+
+
+ std::cout<<rank<<": Unchanged: "<<indexSet<<std::endl<<remoteIndices<<std::endl;
+ assert(areEqual(indexSet, remoteIndices,changedIndexSet, changedRemoteIndices));
+
+ std::cout<<"Deleting entries!"<<std::endl;
+
+ //if(procs==1)
+ //addFakeRemoteIndices(indexSet, changedIndexSet, remoteIndices, changedRemoteIndices);
+
+ deleteOverlapEntries(changedIndexSet, changedRemoteIndices);
+ std::cout<<rank<<": Changed: "<<changedIndexSet<<std::endl<<changedRemoteIndices<<std::endl;
+
+ Dune::IndicesSyncer<ParallelIndexSet> syncer(changedIndexSet, changedRemoteIndices);
+ // return 0;
+
+ std::cout<<"Syncing!"<<std::endl;
+
+ syncer.sync();
+
+ std::cout<<rank<<": Synced: "<<changedIndexSet<<std::endl<<changedRemoteIndices<<std::endl;
+ if( areEqual(indexSet, remoteIndices,changedIndexSet, changedRemoteIndices))
+ return true;
+ else{
+ std::cerr<<"Output not equal!"<<std::endl;
+ return false;
+ }
+
+
+}
+
+/**
+ * @brief MPI Error.
+ * Thrown when an mpi error occurs.
+ */
+class MPIError {
+public:
+ /** @brief Constructor. */
+ MPIError(std::string s, int e) : errorstring(s), errorcode(e){}
+ /** @brief The error string. */
+ std::string errorstring;
+ /** @brief The mpi error code. */
+ int errorcode;
+};
+
+void MPI_err_handler(MPI_Comm *comm, int *err_code, ...){
+ DUNE_UNUSED_PARAMETER(comm);
+ char *err_string=new char[MPI_MAX_ERROR_STRING];
+ int err_length;
+ MPI_Error_string(*err_code, err_string, &err_length);
+ std::string s(err_string, err_length);
+ std::cerr << "An MPI Error ocurred:"<<std::endl<<s<<std::endl;
+ delete[] err_string;
+ throw MPIError(s, *err_code);
+}
+#endif // HAVE_MPI
+
+int main(int argc, char** argv){
+#if HAVE_MPI
+ MPI_Init(&argc, &argv);
+ MPI_Errhandler handler;
+ MPI_Errhandler_create(MPI_err_handler, &handler);
+ MPI_Errhandler_set(MPI_COMM_WORLD, handler);
+ int procs, rank;
+ MPI_Comm_size(MPI_COMM_WORLD, &procs);
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+ bool ret=testIndicesSyncer();
+ MPI_Barrier(MPI_COMM_WORLD);
+ std::cout<<rank<<": ENd="<<ret<<std::endl;
+ if(!ret)
+ MPI_Abort(MPI_COMM_WORLD, 1);
+ MPI_Finalize();
+ return 0;
+#else
+ return 77;
+#endif
+}
--- /dev/null
+#include"config.h"
+#include<iostream>
+#if HAVE_MPI
+#include<mpi.h>
+#endif
+struct MyDataHandle
+{
+ MyDataHandle(int r)
+ : rank(r)
+ {
+ }
+ int rank;
+
+ typedef double DataType;
+
+ bool fixedsize()
+ {
+ return true;
+ }
+ template<class B>
+ void gather(B& buffer, int i)
+ {
+ std::cout<<rank<<": Gathering "<<i<<std::endl;
+ double d=i;
+ buffer.write(d);
+ buffer.write(d);
+ buffer.write(d);
+ }
+ template<class B>
+ void scatter(B& buffer, int i, int size)
+ {
+ std::cout<<rank<<": Scattering "<<size<<" entries for "<<i<<": ";
+ for(;size>0;--size)
+ {
+ double index;
+ buffer.read(index);
+ std::cout<<index<<" ";
+ }
+ std::cout<<std::endl;
+ }
+ std::size_t size(int i)
+ {
+ DUNE_UNUSED_PARAMETER(i);
+ return 3;
+ }
+};
+
+struct VarDataHandle
+{
+ VarDataHandle(int r)
+ : rank(r)
+ {}
+ int rank;
+ typedef double DataType;
+ bool fixedsize()
+ {
+ return false;
+ }
+
+ template<class B>
+ void gather(B& buffer, int i)
+ {
+ std::size_t s=i%5;
+ std::cout<<rank<<": Gathering "<<s<<" entries for index "<<i<<std::endl;
+ for(std::size_t j=0; j<s; j++)
+ buffer.write(static_cast<double>(i+j));
+ }
+ template<class B>
+ void scatter(B& buffer, int i, int size)
+ {
+ std::cout<<rank<<": Scattering "<<size<<" entries for "<<i<<": ";
+ for(;size>0;--size)
+ {
+ double index;
+ buffer.read(index);
+ std::cout<<index<<" ";
+ }
+ std::cout<<std::endl;
+ }
+ std::size_t size(int i)
+ {
+ return i%5;
+ }
+
+};
+
+#include<dune/common/parallel/variablesizecommunicator.hh>
+
+int main(int argc, char** argv)
+{
+#if HAVE_MPI
+ MPI_Init(&argc, &argv);
+ int procs, rank;
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+ MPI_Comm_size(MPI_COMM_WORLD, &procs);
+ if(procs==1)
+ {
+ typedef Dune::VariableSizeCommunicator<>::InterfaceMap Interface;
+ Dune::InterfaceInformation send, recv;
+ send.reserve(6);
+ for(std::size_t i=0; i<=10; i+=2)
+ send.add(i);
+
+ recv.reserve(6);
+ for(std::size_t i=10; i<=10; i-=2)
+ recv.add(i);
+ Interface inf;
+ inf[0]=std::make_pair(send, recv);
+ Dune::VariableSizeCommunicator<> comm(MPI_COMM_SELF, inf, 6);
+ MyDataHandle handle(0);
+ comm.forward(handle);
+ std::cout<<"===================== backward ========================="<<std::endl;
+ comm.backward(handle);
+ std::cout<<"================== variable size ======================="<<std::endl;
+ VarDataHandle vhandle(0);
+ comm.forward(vhandle);
+ std::cout<<"===================== backward ========================="<<std::endl;
+ comm.backward(vhandle);
+ }
+ else
+ {
+ int N=100000;
+ int num_per_proc=N/procs;
+ int start, end;
+ if(rank<N%procs)
+ {
+ start=rank*(num_per_proc+1);
+ end=(rank+1)*(num_per_proc+1);
+ }
+ else
+ {
+ start=(N%procs)+rank*(num_per_proc);
+ end=start+num_per_proc;
+ }
+ if(rank==procs-1)
+ assert(N==end);
+ typedef Dune::VariableSizeCommunicator<>::InterfaceMap Interface;
+ Interface inf;
+ if(rank)
+ {
+ Dune::InterfaceInformation send, recv;
+ send.reserve(2);
+ recv.reserve(2);
+ send.add(start-1);
+ send.add(start);
+ recv.add(start-1);
+ recv.add(start);
+ inf[rank-1]=std::make_pair(send, recv);
+ }
+ if(rank<procs-1)
+ {
+
+ Dune::InterfaceInformation send, recv;
+ send.reserve(2);
+ recv.reserve(2);
+ send.add(end-1);
+ send.add(end);
+ recv.add(end-1);
+ recv.add(end);
+ inf[rank+1]=std::make_pair(send, recv);
+ }
+ Dune::VariableSizeCommunicator<> comm(MPI_COMM_WORLD, inf, 6);
+ MyDataHandle handle(rank);
+ comm.forward(handle);
+ MPI_Barrier(MPI_COMM_WORLD);
+ if(rank==0)
+ std::cout<<"===================== backward ========================="<<std::endl;
+ MPI_Barrier(MPI_COMM_WORLD);
+ comm.backward(handle);
+ MPI_Barrier(MPI_COMM_WORLD);
+ if(rank==0)
+ std::cout<<"================== variable size ======================="<<std::endl;
+ MPI_Barrier(MPI_COMM_WORLD);
+
+ VarDataHandle vhandle(rank);
+ MPI_Barrier(MPI_COMM_WORLD);
+ comm.forward(vhandle);
+ MPI_Barrier(MPI_COMM_WORLD);
+ if(rank==0)
+ std::cout<<"===================== backward ========================="<<std::endl;
+ comm.backward(vhandle);
+ }
+
+ MPI_Finalize();
+#else
+ std::cerr<<"Skipping as MPI seems not be available"<<std::endl;
+ return 77;
+#endif
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_COMMON_PARALLEL_VARIABLESIZECOMMUNICATOR_HH // Still fits the line!
+#define DUNE_COMMON_PARALLEL_VARIABLESIZECOMMUNICATOR_HH
+
+#if HAVE_MPI
+// MPI header
+#include <mpi.h>
+#include <vector>
+#include <map>
+#include <functional>
+#include <dune/common/unused.hh>
+#include "interface.hh"
+#include "mpitraits.hh"
+
+/**
+ * @addtogroup Common_Parallel
+ *
+ * @{
+ */
+/**
+ * @file
+ * @brief A communicator that only needs to know the number of elements per
+ * index at the sender side.
+ * @author Markus Blatt
+ * @}
+ */
+namespace Dune
+{
+
+namespace
+{
+/**
+ * @brief A message buffer.
+ * @tparam T The type of data that the buffer will hold.
+ */
+template<class T, class Allocator=std::allocator<T> >
+class MessageBuffer
+{
+public:
+ /**
+ * @brief Constructs a message.
+ * @param size The number of elements that buffer should hold,
+ */
+ explicit MessageBuffer(int size)
+ : buffer_(new T[size]), size_(size), position_(0)
+ {}
+ /**
+ * @brief Copy constructor.
+ * @param o The instance to copy.
+ */
+ explicit MessageBuffer(const MessageBuffer& o)
+ : buffer_(new T[o.size_]), size_(o.size_), position_(o.position_)
+ {
+ }
+ /** @brief Destructor. */
+ ~MessageBuffer()
+ {
+ delete[] buffer_;
+ }
+ /**
+ * @brief Write an item to the buffer.
+ * @param data The data item to write.
+ */
+ void write(const T& data)
+ {
+ buffer_[position_++]=data;
+ }
+
+ /**
+ * @brief Reads a data item from the buffer
+ * @param[out] data Reference to where to store the read data.
+ */
+ void read(T& data)
+ {
+ data=buffer_[position_++];
+ }
+
+ /**
+ * @brief Reset the buffer.
+ *
+ * On return the buffer will be positioned at the start again.
+ */
+ void reset()
+ {
+ position_=0;
+ }
+
+ /**
+ * @brief Test whether the whole buffer was read.
+ * @return True if we read or wrot until the end of the buffer.
+ */
+ bool finished()
+ {
+ return position_==size_;
+ }
+
+ /**
+ * @brief Tests whether the buffer has enough space left to read/write data.
+ * @param notItems The number of items to read or write.
+ * @return True if there is enough space for noItems items.
+ */
+ bool hasSpaceForItems(int noItems)
+ {
+ return position_+noItems<=size_;
+ }
+ /**
+ * @brief Get the size of the buffer.
+ * @return The number of elements the buffer can hold.
+ */
+ std::size_t size() const
+ {
+ return size_;
+ }
+ /**
+ * @brief Converts the buffer to a C array.
+ * @return The underlying C array.
+ */
+ operator T*()
+ {
+ return buffer_;
+ }
+
+private:
+ /**
+ * @brief Pointer to the current insertion point of the buffer.
+ */
+ T* buffer_;
+ /**
+ * @brief The size of the buffer
+ */
+ std::size_t size_;
+ /**
+ * @brief The current position in the buffer.
+ */
+ std::size_t position_;
+};
+
+/**
+ * @brief A tracker for the current position in a communication interface.
+ */
+class InterfaceTracker
+{
+public:
+ /**
+ * @brief Constructor.
+ * @param rank The other rank that the interface communicates with.
+ * @param info A list of local indices belonging to this interface.
+ */
+ InterfaceTracker(int rank, InterfaceInformation info, std::size_t fixedsize=0,
+ bool allocateSizes=false)
+ : fixedSize(fixedsize),rank_(rank), index_(), interface_(info), sizes_(),
+ sizesAllocated_(allocateSizes)
+ {
+ if(allocateSizes)
+ {
+ sizes_.resize(info.size());
+ }
+ }
+
+ /**
+ * @brief Moves to the next index in the interface.
+ */
+ void moveToNextIndex()
+ {
+ index_++;
+ assert(index_<=interface_.size());
+ skipZeroIndices();
+ }
+ /**
+ * @brief Increment index various times.
+ * @param i The number of times to increment.
+ */
+ void increment(std::size_t i)
+ {
+ index_+=i;
+ assert(index_<=interface_.size());
+ }
+ /**
+ * @brief Checks whether all indices have been visited.
+ * @return True if all indices have been visited.
+ */
+ bool finished() const
+ {
+ return index_==interface_.size();
+ }
+
+ void skipZeroIndices()
+ {
+ // skip indices with size zero!
+ while(sizes_.size() && index_!=interface_.size() &&!size())
+ ++index_;
+ }
+
+ /**
+ * @brief Get the current local index of the interface.
+ * @return The current local index of the interface.
+ */
+ std::size_t index() const
+ {
+ return interface_[index_];
+ }
+ /**
+ * @brief Get the size at the current index.
+ */
+ std::size_t size() const
+ {
+ assert(sizes_.size());
+ return sizes_[index_];
+ }
+ /**
+ * @brief Get a pointer to the array with the sizes.
+ */
+ std::size_t* getSizesPointer()
+ {
+ return &sizes_[0];
+ }
+ /**
+ * @brief Returns whether the interface is empty.
+ * @return True if there are no entries in the interface.
+ */
+ bool empty() const
+ {
+ return !interface_.size();
+ }
+
+ /**
+ * @brief Checks whether there are still indices waiting to be processed.
+ * @return True if there are still indices waiting to be processed.
+ */
+ std::size_t indicesLeft() const
+ {
+ return interface_.size()-index_;
+ }
+ /**
+ * @brief The number of data items per index if it is fixed, 0 otherwise.
+ */
+ std::size_t fixedSize;
+ /**
+ * @brief Get the process rank that this communication interface is with.
+ */
+ int rank() const
+ {
+ return rank_;
+ }
+ /**
+ * @brief Get the offset to the first index.
+ */
+ std::size_t offset() const
+ {
+ return index_;
+ }
+private:
+ /** @brief The process rank that this communication interface is with. */
+ int rank_;
+ /** @brief The other rank that this interface communcates with. */
+ std::size_t index_;
+ /** @brief The list of local indices of this interface. */
+ InterfaceInformation interface_;
+ std::vector<std::size_t> sizes_;
+ bool sizesAllocated_;
+};
+
+
+} // end unnamed namespace
+
+/**
+ * @addtogroup Common_Parallel
+ *
+ * @{
+ */
+/**
+ * @brief A buffered communicator where the amount of data sent does not have to be known a priori.
+ *
+ * In contrast to BufferedCommunicator the amount of data is determined by the container
+ * whose entries are sent and not known at the receiving side a priori.
+ */
+template<class Allocator=std::allocator<std::pair<InterfaceInformation,InterfaceInformation> > >
+class VariableSizeCommunicator
+{
+public:
+ /**
+ * @brief The type of the map form process number to InterfaceInformation for
+ * sending and receiving to and from it.
+ */
+ typedef std::map<int,std::pair<InterfaceInformation,InterfaceInformation>,
+ std::less<int>,
+ typename Allocator::template rebind<std::pair<const int,std::pair<InterfaceInformation,InterfaceInformation> > >::other> InterfaceMap;
+
+#ifndef DUNE_PARALLEL_MAX_COMMUNICATION_BUFFER_SIZE
+ /**
+ * @brief Creates a communicator with the default maximum buffer size.
+ *
+ * The default size ist either what the macro DUNE_MAX_COMMUNICATION_BUFFER_SIZE
+ * is set to or 32768 if is not set.
+ */
+ VariableSizeCommunicator(MPI_Comm comm, const InterfaceMap& inf)
+ : maxBufferSize_(32768), interface_(&inf)
+ {
+ MPI_Comm_dup(comm, &communicator_);
+ }
+ /**
+ * @brief Creates a communicator with the default maximum buffer size.
+ * @param inf The communication interface.
+ */
+ VariableSizeCommunicator(const Interface& inf)
+ : maxBufferSize_(32768), interface_(&inf.interfaces())
+ {
+ MPI_Comm_dup(inf.communicator(), &communicator_);
+ }
+#else
+ /**
+ * @brief Creates a communicator with the default maximum buffer size.
+ *
+ * The default size ist either what the macro DUNE_MAX_COMMUNICATION_BUFFER_SIZE
+ * is set to or 32768 if is not set.
+ */
+ VariableSizeCommunicator(MPI_Comm comm, InterfaceMap& inf)
+ : maxBufferSize_(DUNE_PARALLEL_MAX_COMMUNICATION_BUFFER_SIZE),
+ interface_(&inf)
+ {
+ MPI_Comm_dup(comm, &communicator_);
+ }
+ /**
+ * @brief Creates a communicator with the default maximum buffer size.
+ * @param inf The communication interface.
+ */
+ VariableSizeCommunicator(const Interface& inf)
+ : maxBufferSize_(DUNE_PARALLEL_MAX_COMMUNICATION_BUFFER_SIZE),
+ interface_(&inf.interfaces())
+ {
+ MPI_Comm_dup(inf.communicator(), &communicator_);
+ }
+#endif
+ /**
+ * @brief Creates a communicator with a specific maximum buffer size.
+ * @param comm The MPI communicator to use.
+ * @param inf The communication interface.
+ * @param max_buffer_size The maximum buffer size allowed.
+ */
+ VariableSizeCommunicator(MPI_Comm comm, const InterfaceMap& inf, std::size_t max_buffer_size)
+ : maxBufferSize_(max_buffer_size), interface_(&inf)
+ {
+ MPI_Comm_dup(comm, &communicator_);
+ }
+
+ /**
+ * @brief Creates a communicator with a specific maximum buffer size.
+ * @param inf The communication interface.
+ * @param max_buffer_size The maximum buffer size allowed.
+ */
+ VariableSizeCommunicator(const Interface& inf, std::size_t max_buffer_size)
+ : maxBufferSize_(max_buffer_size), interface_(&inf.interfaces())
+ {
+ MPI_Comm_dup(inf.communicator(), &communicator_);
+ }
+
+ ~VariableSizeCommunicator()
+ {
+ MPI_Comm_free(&communicator_);
+ }
+
+
+ /**
+ * @brief Communicate forward.
+ *
+ * @tparam DataHandle The type of the handle describing the data. This type has to adhere
+ * to the following interface:
+ * \code{.cpp}
+ * // returns whether the number of data items per entry is fixed
+ * bool fixedsize();
+ * // get the number of data items for an entry with index i
+ * std::size_t size(std::size_t i);
+ * // gather the data at index i
+ * template<class MessageBuffer>
+ * void gather(MessageBuffer& buf, std::size_t i);
+ * // scatter the n data items to index i
+ * template<class MessageBuffer>
+ * void scatter(MessageBuffer& buf, std::size_t i, std::size_t n);
+ * \endcode
+ * @param handle A handle responsible for describing the data, gathering, and scattering it.
+ */
+ template<class DataHandle>
+ void forward(DataHandle& handle)
+ {
+ communicate<true>(handle);
+ }
+
+ /**
+ * @brief Communicate backwards.
+ *
+ * @tparam DataHandle The type of the handle describing the data. This type has to adhere
+ * to the following interface:
+ * \code{.cpp}
+ * // returns whether the number of data items per entry is fixed
+ * bool fixedsize();
+ * // get the number of data items for an entry with index i
+ * std::size_t size(std::size_t i);
+ * // gather the data at index i
+ * template<class MessageBuffer>
+ * void gather(MessageBuffer& buf, std::size_t i);
+ * // scatter the n data items to index i
+ * template<class MessageBuffer>
+ * void scatter(MessageBuffer& buf, std::size_t i, std::size_t n);
+ * \endcode
+ * @param handle A handle responsible for describing the data, gathering, and scattering it.
+ */
+ template<class DataHandle>
+ void backward(DataHandle& handle)
+ {
+ communicate<false>(handle);
+ }
+
+private:
+ template<bool FORWARD, class DataHandle>
+ void communicateSizes(DataHandle& handle,
+ std::vector<InterfaceTracker>& recv_trackers);
+
+ /**
+ * @brief Communicates data according to the interface.
+ * @tparam forward If true sends data forwards, otherwise backwards along the interface.
+ * @tparame DataHandle The type of the data handle @see forward for a description of the interface.
+ * @param handle The handle describing the data and responsible for gather and scatter operations.
+ */
+ template<bool forward,class DataHandle>
+ void communicate(DataHandle& handle);
+ /**
+ * @brief Initialize the the trackers along the interface for the communication.
+ * @tparam FORWARD If true we send in the forward direction.
+ * @tparam DataHandle DataHandle The type of the data handle.
+ * @param handle The handle describing the data and responsible for gather
+ * and scatter operations.
+ * @param[out] send_trackers The trackers for the sending side.
+ * @param[out] recv_trackers The trackers for the receiving side.
+ */
+ template<bool FORWARD, class DataHandle>
+ void setupInterfaceTrackers(DataHandle& handle,
+ std::vector<InterfaceTracker>& send_trackers,
+ std::vector<InterfaceTracker>& recv_trackers);
+ /**
+ * @brief Communicate data with a fixed amount of data per entry.
+ * @tparam FORWARD If true we send in the forward direction.
+ * @tparam DataHandle DataHandle The type of the data handle.
+ * @param handle The handle describing the data and responsible for gather
+ * and scatter operations.
+ */
+ template<bool FORWARD, class DataHandle>
+ void communicateFixedSize(DataHandle& handle);
+ /**
+ * @brief Communicate data with a variable amount of data per entry.
+ * @tparam FORWARD If true we send in the forward direction.
+ * @tparam DataHandle DataHandle The type of the data handle.
+ * @param handle The handle describing the data and responsible for gather
+ * and scatter operations.
+ */
+ template<bool FORWARD, class DataHandle>
+ void communicateVariableSize(DataHandle& handle);
+ /**
+ * @brief The maximum size if the buffers used for gather and scatter.
+ *
+ * @note If this process has n neighbours, then a maximum of 2n buffers of this size
+ * is allocate. Memory needed will be n*sizeof(std::size_t)+n*sizeof(Datahandle::DataType)
+ */
+ std::size_t maxBufferSize_;
+ /**
+ * @brief description of the interface.
+ *
+ * This is a map of the neighboring process number to a pair of local index lists.
+ * The first is a list of indices to gather data for sending from and the second is a list of
+ * indices to scatter received data to during forward.
+ */
+ const InterfaceMap* interface_;
+ /**
+ * @brief The communicator.
+ *
+ * This is a cloned communicator to ensure there are no interferences.
+ */
+ MPI_Comm communicator_;
+};
+
+/** @} */
+namespace
+{
+/**
+ * @brief A data handle for comunicating the sizes of variable sized data.
+ */
+template<class DataHandle>
+class SizeDataHandle
+{
+public:
+ typedef std::size_t DataType;
+
+ SizeDataHandle(DataHandle& data,
+ std::vector<InterfaceTracker>& trackers)
+ : data_(data), trackers_(trackers), index_()
+ {}
+ bool fixedsize()
+ {
+ return true;
+ }
+ std::size_t size(std::size_t i)
+ {
+ DUNE_UNUSED_PARAMETER(i);
+ return 1;
+ }
+ template<class B>
+ void gather(B& buf, int i)
+ {
+ buf.write(data_.size(i));
+ }
+ void setReceivingIndex(std::size_t i)
+ {
+ index_=i;
+ }
+ std::size_t* getSizesPointer()
+ {
+ return trackers_[index_].getSizesPointer();
+ }
+
+private:
+ DataHandle& data_;
+ std::vector<InterfaceTracker>& trackers_;
+ int index_;
+};
+
+template<class T>
+void setReceivingIndex(T&, int)
+{}
+
+template<class T>
+void setReceivingIndex(SizeDataHandle<T>& t, int i)
+{
+ t.setReceivingIndex(i);
+}
+
+
+/**
+ * @brief Template meta program for choosing then send or receive interface
+ * information based on the direction.
+ * @tparam FORWARD If true the communication happens in the forward direction.
+ */
+template<bool FORWARD>
+struct InterfaceInformationChooser
+{
+ /**
+ * @brief Get the interface information for the sending side.
+ */
+ static const InterfaceInformation&
+ getSend(const std::pair<InterfaceInformation,InterfaceInformation>& info)
+ {
+ return info.first;
+ }
+
+ /**
+ * @brief Get the interface information for the receiving side.
+ */
+ static const InterfaceInformation&
+ getReceive(const std::pair<InterfaceInformation,InterfaceInformation>& info)
+ {
+ return info.second;
+ }
+};
+
+template<>
+struct InterfaceInformationChooser<false>
+{
+ static const InterfaceInformation&
+ getSend(const std::pair<InterfaceInformation,InterfaceInformation>& info)
+ {
+ return info.second;
+ }
+
+ static const InterfaceInformation&
+ getReceive(const std::pair<InterfaceInformation,InterfaceInformation>& info)
+ {
+ return info.first;
+ }
+};
+
+/**
+ * @brief A functor that packs entries into the message buffer.
+ * @tparam DataHandle The type of the data handle that describes
+ * the communicated data.
+ */
+template<class DataHandle>
+struct PackEntries
+{
+
+ int operator()(DataHandle& handle, InterfaceTracker& tracker,
+ MessageBuffer<typename DataHandle::DataType>& buffer,
+ int i) const
+ {
+ return operator()(handle,tracker,buffer);
+ }
+
+ /**
+ * @brief packs data.
+ * @param handle The handle describing the data and the gather and scatter operations.
+ * @param tracker The tracker of the interface to tell us where we are.
+ * @param buffer The buffer to use for packing.
+ * @return The number data entries that we packed.
+ */
+ int operator()(DataHandle& handle, InterfaceTracker& tracker,
+ MessageBuffer<typename DataHandle::DataType>& buffer) const
+ {
+ if(tracker.fixedSize) // fixed size if variable is >0!
+ {
+
+ std::size_t noIndices=std::min(buffer.size()/tracker.fixedSize, tracker.indicesLeft());
+ for(std::size_t i=0; i< noIndices; ++i)
+ {
+ handle.gather(buffer, tracker.index());
+ tracker.moveToNextIndex();
+ }
+ return noIndices*tracker.fixedSize;
+ }
+ else
+ {
+ int packed=0;
+ tracker.skipZeroIndices();
+ while(!tracker.finished())
+ if(buffer.hasSpaceForItems(handle.size(tracker.index())))
+ {
+ handle.gather(buffer, tracker.index());
+ packed+=handle.size(tracker.index());
+ tracker.moveToNextIndex();
+ }
+ else
+ break;
+ assert(packed);
+ return packed;
+ }
+ }
+};
+
+/**
+ * @brief A functor that unpacks entries from the message buffer.
+ * @tparam DataHandle The type of the data handle that describes
+ * the communicated data.
+ */
+template<class DataHandle>
+struct UnpackEntries{
+
+ /**
+ * @brief packs data.
+ * @param handle The handle describing the data and the gather and scatter operations.
+ * @param tracker The tracker of the interface to tell us where we are.
+ * @param buffer The buffer to use for packing.
+ * @return The number data entries that we packed.
+ */
+ bool operator()(DataHandle& handle, InterfaceTracker& tracker,
+ MessageBuffer<typename DataHandle::DataType>& buffer,
+ int count=0)
+ {
+ if(tracker.fixedSize) // fixed size if variable is >0!
+ {
+ std::size_t noIndices=std::min(buffer.size()/tracker.fixedSize, tracker.indicesLeft());
+
+ for(std::size_t i=0; i< noIndices; ++i)
+ {
+ handle.scatter(buffer, tracker.index(), tracker.fixedSize);
+ tracker.moveToNextIndex();
+ }
+ return tracker.finished();
+ }
+ else
+ {
+ assert(count);
+ for(int unpacked=0;unpacked<count;)
+ {
+ assert(!tracker.finished());
+ assert(buffer.hasSpaceForItems(tracker.size()));
+ handle.scatter(buffer, tracker.index(), tracker.size());
+ unpacked+=tracker.size();
+ tracker.moveToNextIndex();
+ }
+ return tracker.finished();
+ }
+ }
+};
+
+
+/**
+ * @brief A functor that unpacks std::size_t from the message buffer.
+ */
+template<class DataHandle>
+struct UnpackSizeEntries{
+
+ /**
+ * @brief packs data.
+ * @param handle The handle describing the data and the gather and scatter operations.
+ * @param tracker The tracker of the interface to tell us where we are.
+ * @param buffer The buffer to use for packing.
+ * @return The number data entries that we packed.
+ */
+ bool operator()(SizeDataHandle<DataHandle>& handle, InterfaceTracker& tracker,
+ MessageBuffer<typename SizeDataHandle<DataHandle>::DataType>& buffer) const
+ {
+ std::size_t noIndices=std::min(buffer.size(), tracker.indicesLeft());
+ std::copy(static_cast<std::size_t*>(buffer), static_cast<std::size_t*>(buffer)+noIndices,
+ handle.getSizesPointer()+tracker.offset());
+ tracker.increment(noIndices);
+ return noIndices;
+ }
+ bool operator()(SizeDataHandle<DataHandle>& handle, InterfaceTracker& tracker,
+ MessageBuffer<typename SizeDataHandle<DataHandle>::DataType>& buffer, int) const
+ {
+ return operator()(handle,tracker,buffer);
+ }
+};
+
+/**
+ * @brief Sends the size in case of communicating a fixed amount of data per entry.
+ * @param[in] send_trackers The trackers for the sending side.
+ * @param[out] send_requests The request for the asynchronous send operations.
+ * @param[in] recv_trackers The trackers for the receiving side.
+ * @param[out] recv_requests The request for the asynchronous receive operations.
+ */
+void sendFixedSize(std::vector<InterfaceTracker>& send_trackers,
+ std::vector<MPI_Request>& send_requests,
+ std::vector<InterfaceTracker>& recv_trackers,
+ std::vector<MPI_Request>& recv_requests,
+ MPI_Comm communicator)
+{
+ typedef std::vector<InterfaceTracker>::iterator TIter;
+ std::vector<MPI_Request>::iterator mIter=recv_requests.begin();
+
+ for(TIter iter=recv_trackers.begin(), end=recv_trackers.end(); iter!=end;
+ ++iter, ++mIter)
+ {
+ MPI_Irecv(&(iter->fixedSize), 1, MPITraits<std::size_t>::getType(),
+ iter->rank(), 933881, communicator, &(*mIter));
+ }
+
+ // Send our size to all neighbours using non-blocking synchronous communication.
+ std::vector<MPI_Request>::iterator mIter1=send_requests.begin();
+ for(TIter iter=send_trackers.begin(), end=send_trackers.end();
+ iter!=end;
+ ++iter, ++mIter1)
+ {
+ MPI_Issend(&(iter->fixedSize), 1, MPITraits<std::size_t>::getType(),
+ iter->rank(), 933881, communicator, &(*mIter1));
+ }
+}
+
+
+/**
+ * @brief Functor for setting up send requests.
+ * @tparam DataHandle The type of the data handle for describing the data.
+ */
+template<class DataHandle>
+struct SetupSendRequest{
+ void operator()(DataHandle& handle,
+ InterfaceTracker& tracker,
+ MessageBuffer<typename DataHandle::DataType>& buffer,
+ MPI_Request& request,
+ MPI_Comm comm) const
+ {
+ buffer.reset();
+ int size=PackEntries<DataHandle>()(handle, tracker, buffer);
+ // Skip indices of zero size.
+ while(!tracker.finished() && !handle.size(tracker.index()))
+ tracker.moveToNextIndex();
+ if(size)
+ MPI_Issend(buffer, size, MPITraits<typename DataHandle::DataType>::getType(),
+ tracker.rank(), 933399, comm, &request);
+ }
+};
+
+
+/**
+ * @brief Functor for setting up receive requests.
+ * @tparam DataHandle The type of the data handle for describing the data.
+ */
+template<class DataHandle>
+struct SetupRecvRequest{
+ void operator()(DataHandle& /*handle*/,
+ InterfaceTracker& tracker,
+ MessageBuffer<typename DataHandle::DataType>& buffer,
+ MPI_Request& request,
+ MPI_Comm comm) const
+ {
+ buffer.reset();
+ if(tracker.indicesLeft())
+ MPI_Irecv(buffer, buffer.size(), MPITraits<typename DataHandle::DataType>::getType(),
+ tracker.rank(), 933399, comm, &request);
+ }
+};
+
+/**
+ * @brief A functor that does nothing.
+ */
+template<class DataHandle>
+struct NullPackUnpackFunctor
+{
+ int operator()(DataHandle&, InterfaceTracker&,
+ MessageBuffer<typename DataHandle::DataType>&, int)
+ {
+ return 0;
+ }
+ int operator()(DataHandle&, InterfaceTracker&,
+ MessageBuffer<typename DataHandle::DataType>&)
+ {
+ return 0;
+ }
+};
+
+/**
+ * @brief Check whether some of the requests finished and continue send/receive operation.
+ * @tparam DataHandle The type of the data handle describing the data.
+ * @tparam BufferFunctor A functor that packs or unpacks data from the buffer.
+ * E.g. NullPackUnpackFunctor.
+ * @tparam CommunicationFuntor A functor responsible for continuing the communication.
+ * @param handle The data handle describing the data.
+ * @param trackers The trackers indicating the current position in the communication.
+ * @param requests The requests to test whether they finished.
+ * @param requests2 The requests to use for setting up the continuing communication. Might
+ * be the same as requests.
+ * @param comm The MPI communicator to use.
+ * @param buffer_func The functor that does the packing or unpacking of the data.
+ */
+template<class DataHandle, class BufferFunctor, class CommunicationFunctor>
+std::size_t checkAndContinue(DataHandle& handle,
+ std::vector<InterfaceTracker>& trackers,
+ std::vector<MPI_Request>& requests,
+ std::vector<MPI_Request>& requests2,
+ std::vector<MessageBuffer<typename DataHandle::DataType> >& buffers,
+ MPI_Comm comm,
+ BufferFunctor buffer_func,
+ CommunicationFunctor comm_func,
+ bool valid=true,
+ bool getCount=false)
+{
+ std::size_t size=requests.size();
+ std::vector<MPI_Status> statuses(size);
+ int no_completed;
+ std::vector<int> indices(size, -1); // the indices for which the communication finished.
+
+ MPI_Testsome(size, &(requests[0]), &no_completed, &(indices[0]), &(statuses[0]));
+ indices.resize(no_completed);
+ for(std::vector<int>::iterator index=indices.begin(), end=indices.end();
+ index!=end; ++index)
+ {
+ InterfaceTracker& tracker=trackers[*index];
+ setReceivingIndex(handle, *index);
+ if(getCount)
+ {
+ // Get the number of entries received
+ int count;
+ MPI_Get_count(&(statuses[index-indices.begin()]),
+ MPITraits<typename DataHandle::DataType>::getType(),
+ &count);
+ // Communication completed, we can reuse the buffers, e.g. unpack or repack
+ buffer_func(handle, tracker, buffers[*index], count);
+ }else
+ buffer_func(handle, tracker, buffers[*index]);
+ tracker.skipZeroIndices();
+ if(!tracker.finished()){
+ // Maybe start another communication.
+ comm_func(handle, tracker, buffers[*index], requests2[*index], comm);
+ tracker.skipZeroIndices();
+ if(valid)
+ no_completed-=!tracker.finished(); // communication not finished, decrement counter for finished ones.
+ }
+ }
+ return no_completed;
+
+}
+
+/**
+ * @brief Receive the size per data entry and set up requests for receiving the data.
+ * @tparam DataHandle The type of the data handle.
+ * @param trackers The trackers indicating the indices where we send and from which rank.
+ * @param size_requests The requests for receiving the size.
+ * @param data_requests The requests for sending the data.
+ * @param buffers The buffers to use for sending.
+ * @param comm The mpi communicator to use.
+ */
+template<class DataHandle>
+std::size_t receiveSizeAndSetupReceive(DataHandle& handle,
+ std::vector<InterfaceTracker>& trackers,
+ std::vector<MPI_Request>& size_requests,
+ std::vector<MPI_Request>& data_requests,
+ std::vector<MessageBuffer<typename DataHandle::DataType> >& buffers,
+ MPI_Comm comm)
+{
+ return checkAndContinue(handle, trackers, size_requests, data_requests, buffers, comm,
+ NullPackUnpackFunctor<DataHandle>(), SetupRecvRequest<DataHandle>(), false);
+}
+
+/**
+ * @brief Check whether send request completed and continue sending if necessary.
+ * @tparam DataHandle The type of the data handle.
+ * @param trackers The trackers indicating the indices where we send and from which rank.
+ * @param requests The requests for the asynchronous communication.
+ * @param buffers The buffers to use for sending.
+ * @param comm The mpi communicator to use.
+ */
+template<class DataHandle>
+std::size_t checkSendAndContinueSending(DataHandle& handle,
+ std::vector<InterfaceTracker>& trackers,
+ std::vector<MPI_Request>& requests,
+ std::vector<MessageBuffer<typename DataHandle::DataType> >& buffers,
+ MPI_Comm comm)
+{
+ return checkAndContinue(handle, trackers, requests, requests, buffers, comm,
+ NullPackUnpackFunctor<DataHandle>(), SetupSendRequest<DataHandle>());
+}
+
+/**
+ * @brief Check whether receive request completed and continue receiving if necessary.
+ * @tparam DataHandle The type of the data handle.
+ * @param trackers The trackers indicating the indices where we receive and from which rank.
+ * @param requests The requests for the asynchronous communication.
+ * @param buffers The buffers to use for receiving.
+ * @param comm The mpi communicator to use.
+ */
+template<class DataHandle>
+std::size_t checkReceiveAndContinueReceiving(DataHandle& handle,
+ std::vector<InterfaceTracker>& trackers,
+ std::vector<MPI_Request>& requests,
+ std::vector<MessageBuffer<typename DataHandle::DataType> >& buffers,
+ MPI_Comm comm)
+{
+ return checkAndContinue(handle, trackers, requests, requests, buffers, comm,
+ UnpackEntries<DataHandle>(), SetupRecvRequest<DataHandle>(),
+ true, !handle.fixedsize());
+}
+
+
+bool validRecvRequests(const std::vector<MPI_Request> reqs)
+{
+ for(std::vector<MPI_Request>::const_iterator i=reqs.begin(), end=reqs.end();
+ i!=end; ++i)
+ if(*i!=MPI_REQUEST_NULL)
+ return true;
+ return false;
+}
+
+/**
+ * @brief Sets up all the send requests for the data.
+ * @tparam DataHandle The type of the data handle.
+ * @tparam Functor The type of the functor to set up the request.
+ * @param handle The data handle describing the data.
+ * @param trackers The trackers for the communication interfaces.
+ * @param buffers The buffers for the comunication. One for each neighbour.
+ * @param requests The send requests for each neigbour.
+ * @param setupFunctor The functor responsible for setting up the request.
+ */
+template<class DataHandle, class Functor>
+std::size_t setupRequests(DataHandle& handle,
+ std::vector<InterfaceTracker>& trackers,
+ std::vector<MessageBuffer<typename DataHandle::DataType> >& buffers,
+ std::vector<MPI_Request>& requests,
+ const Functor& setupFunctor,
+ MPI_Comm communicator)
+{
+ typedef typename std::vector<InterfaceTracker>::iterator TIter;
+ typename std::vector<MessageBuffer<typename DataHandle::DataType> >::iterator
+ biter=buffers.begin();
+ typename std::vector<MPI_Request>::iterator riter=requests.begin();
+ std::size_t complete=0;
+ for(TIter titer=trackers.begin(), end=trackers.end(); titer!=end; ++titer, ++biter, ++riter)
+ {
+ setupFunctor(handle, *titer, *biter, *riter, communicator);
+ complete+=titer->finished();
+ }
+ return complete;
+}
+} // end unnamed namespace
+
+template<class Allocator>
+template<bool FORWARD, class DataHandle>
+void VariableSizeCommunicator<Allocator>::setupInterfaceTrackers(DataHandle& handle,
+ std::vector<InterfaceTracker>& send_trackers,
+ std::vector<InterfaceTracker>& recv_trackers)
+{
+ if(interface_->size()==0)
+ return;
+ send_trackers.reserve(interface_->size());
+ recv_trackers.reserve(interface_->size());
+
+ int fixedsize=0;
+ if(handle.fixedsize())
+ ++fixedsize;
+
+
+ typedef typename InterfaceMap::const_iterator IIter;
+ for(IIter inf=interface_->begin(), end=interface_->end(); inf!=end; ++inf)
+ {
+
+ if(handle.fixedsize() && InterfaceInformationChooser<FORWARD>::getSend(inf->second).size())
+ fixedsize=handle.size(InterfaceInformationChooser<FORWARD>::getSend(inf->second)[0]);
+ assert(!handle.fixedsize()||fixedsize>0);
+ send_trackers.push_back(InterfaceTracker(inf->first,
+ InterfaceInformationChooser<FORWARD>::getSend(inf->second), fixedsize));
+ recv_trackers.push_back(InterfaceTracker(inf->first,
+ InterfaceInformationChooser<FORWARD>::getReceive(inf->second), fixedsize, fixedsize==0));
+ }
+}
+
+template<class Allocator>
+template<bool FORWARD, class DataHandle>
+void VariableSizeCommunicator<Allocator>::communicateFixedSize(DataHandle& handle)
+{
+ std::vector<MPI_Request> size_send_req(interface_->size());
+ std::vector<MPI_Request> size_recv_req(interface_->size());
+
+ std::vector<InterfaceTracker> send_trackers;
+ std::vector<InterfaceTracker> recv_trackers;
+ setupInterfaceTrackers<FORWARD>(handle,send_trackers, recv_trackers);
+ sendFixedSize(send_trackers, size_send_req, recv_trackers, size_recv_req, communicator_);
+
+ std::vector<MPI_Request> data_send_req(interface_->size(), MPI_REQUEST_NULL);
+ std::vector<MPI_Request> data_recv_req(interface_->size(), MPI_REQUEST_NULL);
+ typedef typename DataHandle::DataType DataType;
+ std::vector<MessageBuffer<DataType> > send_buffers(interface_->size(), MessageBuffer<DataType>(maxBufferSize_)),
+ recv_buffers(interface_->size(), MessageBuffer<DataType>(maxBufferSize_));
+
+
+ setupRequests(handle, send_trackers, send_buffers, data_send_req,
+ SetupSendRequest<DataHandle>(), communicator_);
+
+ std::size_t no_size_to_recv, no_to_send, no_to_recv, old_size;
+ no_size_to_recv = no_to_send = no_to_recv = old_size = interface_->size();
+
+ // Skip empty interfaces.
+ typedef typename std::vector<InterfaceTracker>::const_iterator Iter;
+ for(Iter i=recv_trackers.begin(), end=recv_trackers.end(); i!=end; ++i)
+ if(i->empty())
+ --no_to_recv;
+ for(Iter i=send_trackers.begin(), end=send_trackers.end(); i!=end; ++i)
+ if(i->empty())
+ --no_to_send;
+
+ while(no_size_to_recv+no_to_send+no_to_recv)
+ {
+ // Receive the fixedsize and setup receives accordingly
+ if(no_size_to_recv)
+ no_size_to_recv -= receiveSizeAndSetupReceive(handle,recv_trackers, size_recv_req,
+ data_recv_req, recv_buffers,
+ communicator_);
+
+ // Check send completion and initiate other necessary sends
+ if(no_to_send)
+ no_to_send -= checkSendAndContinueSending(handle, send_trackers, data_send_req,
+ send_buffers, communicator_);
+ if(validRecvRequests(data_recv_req))
+ // Receive data and setup new unblocking receives if necessary
+ no_to_recv -= checkReceiveAndContinueReceiving(handle, recv_trackers, data_recv_req,
+ recv_buffers, communicator_);
+ }
+
+ // Wait for completion of sending the size.
+ //std::vector<MPI_Status> statuses(interface_->size(), MPI_STATUSES_IGNORE);
+ MPI_Waitall(size_send_req.size(), &(size_send_req[0]), MPI_STATUSES_IGNORE);
+
+}
+
+template<class Allocator>
+template<bool FORWARD, class DataHandle>
+void VariableSizeCommunicator<Allocator>::communicateSizes(DataHandle& handle,
+ std::vector<InterfaceTracker>& data_recv_trackers)
+{
+ std::vector<InterfaceTracker> send_trackers;
+ std::vector<InterfaceTracker> recv_trackers;
+ std::size_t size = interface_->size();
+ std::vector<MPI_Request> send_requests(size);
+ std::vector<MPI_Request> recv_requests(size);
+ std::vector<MessageBuffer<std::size_t> >
+ send_buffers(size, MessageBuffer<std::size_t>(maxBufferSize_)),
+ recv_buffers(size, MessageBuffer<std::size_t>(maxBufferSize_));
+ SizeDataHandle<DataHandle> size_handle(handle,data_recv_trackers);
+ setupInterfaceTrackers<FORWARD>(size_handle,send_trackers, recv_trackers);
+ std::size_t size_to_send=size, size_to_recv=size;
+
+ // Skip empty interfaces.
+ typedef typename std::vector<InterfaceTracker>::const_iterator Iter;
+ for(Iter i=recv_trackers.begin(), end=recv_trackers.end(); i!=end; ++i)
+ if(i->empty())
+ --size_to_recv;
+
+ size_to_send -= setupRequests(size_handle, send_trackers, send_buffers, send_requests,
+ SetupSendRequest<SizeDataHandle<DataHandle> >(), communicator_);
+ setupRequests(size_handle, recv_trackers, recv_buffers, recv_requests,
+ SetupRecvRequest<SizeDataHandle<DataHandle> >(), communicator_);
+
+
+ while(size_to_send+size_to_recv)
+ {
+ if(size_to_send)
+ size_to_send -=
+ checkSendAndContinueSending(size_handle, send_trackers, send_requests,
+ send_buffers, communicator_);
+ if(size_to_recv)
+ // Could have done this using checkSendAndContinueSending
+ // But the call below is more efficient as UnpackSizeEntries
+ // uses std::copy.
+ size_to_recv -=
+ checkAndContinue(size_handle, recv_trackers, recv_requests, recv_requests,
+ recv_buffers, communicator_, UnpackSizeEntries<DataHandle>(),
+ SetupRecvRequest<SizeDataHandle<DataHandle> >());
+ }
+}
+
+template<class Allocator>
+template<bool FORWARD, class DataHandle>
+void VariableSizeCommunicator<Allocator>::communicateVariableSize(DataHandle& handle)
+{
+
+ std::vector<InterfaceTracker> send_trackers;
+ std::vector<InterfaceTracker> recv_trackers;
+ setupInterfaceTrackers<FORWARD>(handle, send_trackers, recv_trackers);
+
+ std::vector<MPI_Request> send_requests(interface_->size(), MPI_REQUEST_NULL);
+ std::vector<MPI_Request> recv_requests(interface_->size(), MPI_REQUEST_NULL);
+ typedef typename DataHandle::DataType DataType;
+ std::vector<MessageBuffer<DataType> >
+ send_buffers(interface_->size(), MessageBuffer<DataType>(maxBufferSize_)),
+ recv_buffers(interface_->size(), MessageBuffer<DataType>(maxBufferSize_));
+
+ communicateSizes<FORWARD>(handle, recv_trackers);
+ std::size_t no_to_send, no_to_recv;
+ no_to_send = no_to_recv = interface_->size();
+ // Setup requests for sending and receiving.
+ no_to_send -= setupRequests(handle, send_trackers, send_buffers, send_requests,
+ SetupSendRequest<DataHandle>(), communicator_);
+ setupRequests(handle, recv_trackers, recv_buffers, recv_requests,
+ SetupRecvRequest<DataHandle>(), communicator_);
+
+ while(no_to_send+no_to_recv)
+ {
+ // Check send completion and initiate other necessary sends
+ if(no_to_send)
+ no_to_send -= checkSendAndContinueSending(handle, send_trackers, send_requests,
+ send_buffers, communicator_);
+ if(no_to_recv)
+ // Receive data and setup new unblocking receives if necessary
+ no_to_recv -= checkReceiveAndContinueReceiving(handle, recv_trackers, recv_requests,
+ recv_buffers, communicator_);
+ }
+}
+
+template<class Allocator>
+template<bool FORWARD, class DataHandle>
+void VariableSizeCommunicator<Allocator>::communicate(DataHandle& handle)
+{
+ if(handle.fixedsize())
+ communicateFixedSize<FORWARD>(handle);
+ else
+ communicateVariableSize<FORWARD>(handle);
+}
+} // end namespace Dune
+#endif
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <cstdlib>
+#include <iostream>
+#include <ostream>
+#include <string>
+#include <sstream>
+#include <fstream>
+#include <set>
+#include <algorithm>
+
+#include <dune/common/exceptions.hh>
+#include <dune/common/parametertree.hh>
+
+using namespace Dune;
+
+ParameterTree::ParameterTree()
+{}
+
+void ParameterTree::report(std::ostream& stream, const std::string& prefix) const
+{
+ typedef std::map<std::string, std::string>::const_iterator ValueIt;
+ ValueIt vit = values.begin();
+ ValueIt vend = values.end();
+
+ for(; vit!=vend; ++vit)
+ stream << vit->first << " = \"" << vit->second << "\"" << std::endl;
+
+ typedef std::map<std::string, ParameterTree>::const_iterator SubIt;
+ SubIt sit = subs.begin();
+ SubIt send = subs.end();
+ for(; sit!=send; ++sit)
+ {
+ stream << "[ " << prefix + sit->first << " ]" << std::endl;
+ (sit->second).report(stream, prefix + sit->first + ".");
+ }
+}
+
+bool ParameterTree::hasKey(const std::string& key) const
+{
+ std::string::size_type dot = key.find(".");
+
+ if (dot != std::string::npos)
+ {
+ std::string prefix = key.substr(0,dot);
+ if (subs.count(prefix) == 0)
+ return false;
+
+ const ParameterTree& s = sub(prefix);
+ return s.hasKey(key.substr(dot+1));
+ }
+ else
+ return (values.count(key) != 0);
+}
+
+bool ParameterTree::hasSub(const std::string& key) const
+{
+ std::string::size_type dot = key.find(".");
+
+ if (dot != std::string::npos)
+ {
+ std::string prefix = key.substr(0,dot);
+ if (subs.count(prefix) == 0)
+ return false;
+
+ const ParameterTree& s = sub(prefix);
+ return s.hasSub(key.substr(dot+1));
+ }
+ else
+ return (subs.count(key) != 0);
+}
+
+ParameterTree& ParameterTree::sub(const std::string& key)
+{
+ std::string::size_type dot = key.find(".");
+
+ if (dot != std::string::npos)
+ {
+ ParameterTree& s = sub(key.substr(0,dot));
+ return s.sub(key.substr(dot+1));
+ }
+ else
+ {
+ if (subs.count(key) == 0)
+ subKeys.push_back(key.substr(0,dot));
+ return subs[key];
+ }
+}
+
+const ParameterTree& ParameterTree::sub(const std::string& key) const
+{
+ std::string::size_type dot = key.find(".");
+
+ if (dot != std::string::npos)
+ {
+ const ParameterTree& s = sub(key.substr(0,dot));
+ return s.sub(key.substr(dot+1));
+ }
+ else
+ {
+ if (subs.count(key) == 0)
+ DUNE_THROW(Dune::RangeError, "Key '" << key << "' not found in ParameterTree");
+ return subs.find(key)->second;
+ }
+}
+
+std::string& ParameterTree::operator[] (const std::string& key)
+{
+ std::string::size_type dot = key.find(".");
+
+ if (dot != std::string::npos)
+ {
+ if (not (hasSub(key.substr(0,dot))))
+ {
+ subs[key.substr(0,dot)];
+ subKeys.push_back(key.substr(0,dot));
+ }
+ ParameterTree& s = sub(key.substr(0,dot));
+ return s[key.substr(dot+1)];
+ }
+ else
+ {
+ if (not (hasKey(key)))
+ valueKeys.push_back(key);
+ return values[key];
+ }
+}
+
+const std::string& ParameterTree::operator[] (const std::string& key) const
+{
+ std::string::size_type dot = key.find(".");
+
+ if (dot != std::string::npos)
+ {
+ if (not (hasSub(key.substr(0,dot))))
+ DUNE_THROW(Dune::RangeError, "Key '" << key << "' not found in ParameterTree");
+ const ParameterTree& s = sub(key.substr(0,dot));
+ return s[key.substr(dot+1)];
+ }
+ else
+ {
+ if (not (hasKey(key)))
+ DUNE_THROW(Dune::RangeError, "Key '" << key << "' not found in ParameterTree");
+ return values.find(key)->second;
+ }
+}
+
+std::string ParameterTree::get(const std::string& key, const std::string& defaultValue) const
+{
+ if (hasKey(key))
+ return (*this)[key];
+ else
+ return defaultValue;
+}
+
+std::string ParameterTree::get(const std::string& key, const char* defaultValue) const
+{
+ if (hasKey(key))
+ return (*this)[key];
+ else
+ return defaultValue;
+}
+
+
+int ParameterTree::get(const std::string& key, int defaultValue) const
+{
+ std::stringstream stream;
+ stream << defaultValue;
+ std::string ret = get(key, stream.str());
+
+ return atoi(ret.c_str());
+}
+
+double ParameterTree::get(const std::string& key, double defaultValue) const
+{
+ if(hasKey(key))
+ return atof((*this)[key].c_str());
+ else
+ return defaultValue;
+}
+
+std::string ParameterTree::ltrim(const std::string& s)
+{
+ std::size_t firstNonWS = s.find_first_not_of(" \t\n\r");
+
+ if (firstNonWS!=std::string::npos)
+ return s.substr(firstNonWS);
+ return std::string();
+}
+
+std::string ParameterTree::rtrim(const std::string& s)
+{
+ std::size_t lastNonWS = s.find_last_not_of(" \t\n\r");
+
+ if (lastNonWS!=std::string::npos)
+ return s.substr(0, lastNonWS+1);
+ return std::string();
+}
+
+std::vector<std::string> ParameterTree::split(const std::string & s) {
+ std::vector<std::string> substrings;
+ std::size_t front = 0, back = 0, size = 0;
+
+ while (front != std::string::npos)
+ {
+ // find beginning of substring
+ front = s.find_first_not_of(" \t\n\r", back);
+ back = s.find_first_of(" \t\n\r", front);
+ size = back - front;
+ if (size > 0)
+ substrings.push_back(s.substr(front, size));
+ }
+ return substrings;
+}
+
+const ParameterTree::KeyVector& ParameterTree::getValueKeys() const
+{
+ return valueKeys;
+}
+
+const ParameterTree::KeyVector& ParameterTree::getSubKeys() const
+{
+ return subKeys;
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_PARAMETERTREE_HH
+#define DUNE_PARAMETERTREE_HH
+
+/** \file
+ * \brief A hierarchical structure of string parameters
+ */
+
+#include <cstddef>
+#include <iostream>
+#include <istream>
+#include <iterator>
+#include <map>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <typeinfo>
+#include <vector>
+#include <algorithm>
+#include <cctype>
+
+#include <dune/common/array.hh>
+#include <dune/common/exceptions.hh>
+#include <dune/common/fvector.hh>
+#include <dune/common/classname.hh>
+
+namespace Dune {
+
+ /** \brief Hierarchical structure of string parameters
+ * \ingroup Common
+ */
+ class ParameterTree
+ {
+ // class providing a single static parse() function, used by the
+ // generic get() method
+ template<typename T>
+ struct Parser;
+
+ public:
+
+ /** \brief storage for key lists
+ */
+ typedef std::vector<std::string> KeyVector;
+
+ /** \brief Create new empty ParameterTree
+ */
+ ParameterTree();
+
+
+ /** \brief test for key
+ *
+ * Tests whether given key exists.
+ *
+ * \param key key name
+ * \return true if key exists in structure, otherwise false
+ */
+ bool hasKey(const std::string& key) const;
+
+
+ /** \brief test for substructure
+ *
+ * Tests whether given substructure exists.
+ *
+ * \param sub substructure name
+ * \return true if substructure exists in structure, otherwise false
+ */
+ bool hasSub(const std::string& sub) const;
+
+
+ /** \brief get value reference for key
+ *
+ * Returns reference to value for given key name.
+ * This creates the key, if not existent.
+ *
+ * \param key key name
+ * \return reference to corresponding value
+ */
+ std::string& operator[] (const std::string& key);
+
+
+ /** \brief get value reference for key
+ *
+ * Returns reference to value for given key name.
+ * This creates the key, if not existent.
+ *
+ * \param key key name
+ * \return reference to corresponding value
+ * \throw Dune::RangeError if key is not found
+ */
+ const std::string& operator[] (const std::string& key) const;
+
+
+ /** \brief print distinct substructure to stream
+ *
+ * Prints all entries with given prefix.
+ *
+ * \param stream Stream to print to
+ * \param prefix for key and substructure names
+ */
+ void report(std::ostream& stream = std::cout,
+ const std::string& prefix = "") const;
+
+
+ /** \brief get substructure by name
+ *
+ * \param sub substructure name
+ * \return reference to substructure
+ */
+ ParameterTree& sub(const std::string& sub);
+
+
+ /** \brief get const substructure by name
+ *
+ * \param sub substructure name
+ * \return reference to substructure
+ */
+ const ParameterTree& sub(const std::string& sub) const;
+
+
+ /** \brief get value as string
+ *
+ * Returns pure string value for given key.
+ *
+ * \param key key name
+ * \param defaultValue default if key does not exist
+ * \return value as string
+ */
+ std::string get(const std::string& key, const std::string& defaultValue) const;
+
+ /** \brief get value as string
+ *
+ * Returns pure string value for given key.
+ *
+ * \todo This is a hack so get("my_key", "xyz") compiles
+ * (without this method "xyz" resolves to bool instead of std::string)
+ * \param key key name
+ * \param defaultValue default if key does not exist
+ * \return value as string
+ */
+ std::string get(const std::string& key, const char* defaultValue) const;
+
+
+ /** \brief get value as int
+ *
+ * Returns value for given key interpreted as int.
+ *
+ * \param key key name
+ * \param defaultValue default if key does not exist
+ * \return value as int
+ */
+ int get(const std::string& key, int defaultValue) const;
+
+
+ /** \brief get value as double
+ *
+ * Returns value for given key interpreted as double.
+ *
+ * \param key key name
+ * \param defaultValue default if key does not exist
+ * \return value as double
+ */
+ double get(const std::string& key, double defaultValue) const;
+
+
+ /** \brief get value converted to a certain type
+ *
+ * Returns value as type T for given key.
+ *
+ * \tparam T type of returned value.
+ * \param key key name
+ * \param defaultValue default if key does not exist
+ * \return value converted to T
+ */
+ template<typename T>
+ T get(const std::string& key, const T& defaultValue) const {
+ if(hasKey(key))
+ return get<T>(key);
+ else
+ return defaultValue;
+ }
+
+ /** \brief Get value
+ *
+ * \tparam T Type of the value
+ * \param key Key name
+ * \throws RangeError if key does not exist
+ * \throws NotImplemented Type is not supported
+ * \return value as T
+ */
+ template <class T>
+ T get(const std::string& key) const {
+ if(not hasKey(key))
+ DUNE_THROW(RangeError, "Key '" << key << "' not found in parameter "
+ "file!");
+ try {
+ return Parser<T>::parse((*this)[key]);
+ }
+ catch(const RangeError&) {
+ DUNE_THROW(RangeError, "Cannot parse value \"" <<
+ (*this)[key] << "\" for key \"" << key << "\" as a " <<
+ className<T>());
+ }
+ }
+
+ /** \brief get value keys
+ *
+ * Returns a vector of all keys associated to (key,values) entries in
+ * order of appearance
+ *
+ * \return reference to entry vector
+ */
+ const KeyVector& getValueKeys() const;
+
+
+ /** \brief get substructure keys
+ *
+ * Returns a vector of all keys associated to (key,substructure) entries
+ * in order of appearance
+ *
+ * \return reference to entry vector
+ */
+ const KeyVector& getSubKeys() const;
+
+ protected:
+ KeyVector valueKeys;
+ KeyVector subKeys;
+
+ std::map<std::string, std::string> values;
+ std::map<std::string, ParameterTree> subs;
+ static std::string ltrim(const std::string& s);
+ static std::string rtrim(const std::string& s);
+ static std::vector<std::string> split(const std::string & s);
+
+ // parse into a fixed-size range of iterators
+ template<class Iterator>
+ static void parseRange(const std::string &str,
+ Iterator it, const Iterator &end)
+ {
+ typedef typename std::iterator_traits<Iterator>::value_type Value;
+ std::istringstream s(str);
+ std::size_t n = 0;
+ for(; it != end; ++it, ++n) {
+ s >> *it;
+ if(!s)
+ DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a "
+ "range of items of type " << className<Value>() << " "
+ "(" << n << " items were extracted successfully)");
+ }
+ Value dummy;
+ s >> dummy;
+ // now extraction should have failed, and eof should be set
+ if(not s.fail() or not s.eof())
+ DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a "
+ "range of " << n << " items of type "
+ << className<Value>() << " (more items than the range "
+ "can hold)");
+ }
+ };
+
+ template<typename T>
+ struct ParameterTree::Parser {
+ static T parse(const std::string& str) {
+ T val;
+ std::istringstream s(str);
+ s >> val;
+ if(!s)
+ DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a " <<
+ className<T>());
+ T dummy;
+ s >> dummy;
+ // now extraction should have failed, and eof should be set
+ if(not s.fail() or not s.eof())
+ DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a " <<
+ className<T>());
+ return val;
+ }
+ };
+
+ // "How do I convert a string into a wstring in C++?" "Why, that very simple
+ // son. You just need a these hundred lines of code."
+ // Instead im gonna restrict myself to string with charT=char here
+ template<typename traits, typename Allocator>
+ struct ParameterTree::Parser<std::basic_string<char, traits, Allocator> > {
+ static std::basic_string<char, traits, Allocator>
+ parse(const std::string& str) {
+ std::string trimmed = ltrim(rtrim(str));
+ return std::basic_string<char, traits, Allocator>(trimmed.begin(),
+ trimmed.end());
+ }
+ };
+
+ template<>
+ struct ParameterTree::Parser< bool > {
+ struct ToLower {
+ int operator()(int c)
+ {
+ return std::tolower(c);
+ }
+ };
+
+ static bool
+ parse(const std::string& str) {
+ std::string ret = str;
+
+ std::transform(ret.begin(), ret.end(), ret.begin(), ToLower());
+
+ if (ret == "yes" || ret == "true")
+ return true;
+
+ if (ret == "no" || ret == "false")
+ return false;
+
+ return (Parser<int>::parse(ret) != 0);
+ }
+ };
+
+ template<typename T, int n>
+ struct ParameterTree::Parser<FieldVector<T, n> > {
+ static FieldVector<T, n>
+ parse(const std::string& str) {
+ FieldVector<T, n> val;
+ parseRange(str, val.begin(), val.end());
+ return val;
+ }
+ };
+
+ template<typename T, std::size_t n>
+ struct ParameterTree::Parser<array<T, n> > {
+ static array<T, n>
+ parse(const std::string& str) {
+ array<T, n> val;
+ parseRange(str, val.begin(), val.end());
+ return val;
+ }
+ };
+
+ template<typename T, typename A>
+ struct ParameterTree::Parser<std::vector<T, A> > {
+ static std::vector<T, A>
+ parse(const std::string& str) {
+ std::vector<std::string> sub = split(str);
+ std::vector<T, A> vec;
+ for (unsigned int i=0; i<sub.size(); ++i) {
+ T val = ParameterTree::Parser<T>::parse(sub[i]);
+ vec.push_back(val);
+ }
+ return vec;
+ }
+ };
+
+} // end namespace Dune
+
+#endif // DUNE_PARAMETERTREE_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "parametertreeparser.hh"
+
+#include <cstdlib>
+#include <iostream>
+#include <ostream>
+#include <string>
+#include <sstream>
+#include <fstream>
+#include <set>
+
+#include <dune/common/exceptions.hh>
+
+std::string Dune::ParameterTreeParser::ltrim(const std::string& s)
+{
+ std::size_t firstNonWS = s.find_first_not_of(" \t\n\r");
+
+ if (firstNonWS!=std::string::npos)
+ return s.substr(firstNonWS);
+ return std::string();
+}
+
+std::string Dune::ParameterTreeParser::rtrim(const std::string& s)
+{
+ std::size_t lastNonWS = s.find_last_not_of(" \t\n\r");
+
+ if (lastNonWS!=std::string::npos)
+ return s.substr(0, lastNonWS+1);
+ return std::string();
+}
+
+
+
+void Dune::ParameterTreeParser::readINITree(std::string file,
+ ParameterTree& pt,
+ bool overwrite)
+{
+ std::ifstream in(file.c_str());
+
+ if (!in)
+ DUNE_THROW(Dune::IOError, "Could not open configuration file " << file);
+
+ readINITree(in, pt, "file '" + file + "'", overwrite);
+}
+
+
+void Dune::ParameterTreeParser::readINITree(std::istream& in,
+ ParameterTree& pt,
+ bool overwrite)
+{
+ readINITree(in, pt, "stream", overwrite);
+}
+
+
+void Dune::ParameterTreeParser::readINITree(std::istream& in,
+ ParameterTree& pt,
+ const std::string srcname,
+ bool overwrite)
+{
+ std::string prefix;
+ std::set<std::string> keysInFile;
+ while(!in.eof())
+ {
+ std::string line;
+ getline(in, line);
+ line = ltrim(line);
+ switch (line[0]) {
+ case '#' :
+ break;
+ case '[' :
+ line = rtrim(line);
+ if (line[line.length()-1] == ']')
+ {
+ prefix = rtrim(ltrim(line.substr(1, line.length()-2)));
+ if (prefix != "")
+ prefix += ".";
+ }
+ break;
+ default :
+ std::string::size_type comment = line.find("#");
+ line = line.substr(0,comment);
+ std::string::size_type mid = line.find("=");
+ if (mid != std::string::npos)
+ {
+ std::string key = prefix+rtrim(ltrim(line.substr(0, mid)));
+ std::string value = ltrim(line.substr(mid+1));
+
+ if (value.length()>0)
+ {
+ // handle quoted strings
+ if ((value[0]=='\'')or (value[0]=='"'))
+ {
+ char quote = value[0];
+ value=value.substr(1);
+ while (*(rtrim(value).rbegin())!=quote)
+ {
+ if (not in.eof())
+ {
+ std::string l;
+ getline(in, l);
+ value = value+"\n"+l;
+ }
+ else
+ value = value+quote;
+ }
+ value = rtrim(value);
+ value = value.substr(0,value.length()-1);
+ }
+ else
+ value = rtrim(value);
+ }
+
+ if (keysInFile.count(key) != 0)
+ DUNE_THROW(Exception, "Key '" << key <<
+ "' appears twice in " << srcname << " !");
+ else
+ {
+ if(overwrite || ! pt.hasKey(key))
+ pt[key] = value;
+ keysInFile.insert(key);
+ }
+ }
+ break;
+ }
+ }
+
+}
+
+
+void Dune::ParameterTreeParser::readOptions(int argc, char* argv [],
+ ParameterTree& pt)
+{
+ std::string v = "";
+ std::string k = "";
+
+ for(int i=1; i<argc; i++)
+ {
+ std::string s(argv[i]);
+
+ if ((argv[i][0]=='-') && (argv[i][1]!='\000'))
+ {
+ k = argv[i]+1;
+ continue;
+ }
+ else
+ {
+ if (k.size())
+ pt[k] = argv[i];
+ k.clear();
+ }
+
+ }
+
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_PARAMETER_PARSER_HH
+#define DUNE_PARAMETER_PARSER_HH
+
+/** \file
+ * \brief Various parser methods to get data into a ParameterTree object
+ */
+
+#include <istream>
+#include <string>
+
+#include <dune/common/parametertree.hh>
+
+namespace Dune {
+
+ /** \brief Parsers to set up a ParameterTree from various input sources
+ * \ingroup Common
+ *
+ */
+ class ParameterTreeParser
+ {
+
+ static std::string ltrim(const std::string& s);
+ static std::string rtrim(const std::string& s);
+
+ public:
+
+ /** @name Parsing methods for the INITree file format
+ *
+ * INITree files should look like this
+ * \verbatim
+ * # this file configures fruit colors in fruitsalad
+ *
+ *
+ * #these are no fruit but could also appear in fruit salad
+ * honeydewmelon = yellow
+ * watermelon = green
+ *
+ * fruit.tropicalfruit.orange = orange
+ *
+ * [fruit]
+ * strawberry = red
+ * pomegranate = red
+ *
+ * [fruit.pipfruit]
+ * apple = green/red/yellow
+ * pear = green
+ *
+ * [fruit.stonefruit]
+ * cherry = red
+ * plum = purple
+ *
+ * \endverbatim
+ *
+ *
+ * If a '[prefix]' statement appears all following entries use this prefix
+ * until the next '[prefix]' statement. Fruitsalads for example contain:
+ * \verbatim
+ * honeydewmelon = yellow
+ * fruit.tropicalfruit.orange = orange
+ * fruit.pipfruit.apple = green/red/yellow
+ * fruit.stonefruit.cherry = red
+ * \endverbatim
+ *
+ * All keys with a common 'prefix.' belong to the same substructure called
+ * 'prefix'. Leading and trailing spaces and tabs are removed from the
+ * values unless you use single or double quotes around them. Using single
+ * or double quotes you can also have multiline values.
+ */
+ //@{
+
+ /** \brief parse C++ stream
+ *
+ * Parses C++ stream and build hierarchical config structure.
+ *
+ * \param in The stream to parse
+ * \param pt The parameter tree to store the config structure.
+ * \param overwrite Whether to overwrite already existing values.
+ * If false, values in the stream will be ignored
+ * if the key is already present.
+ *
+ * \note This method is identical to parseStream(std::istream&,
+ * const std::string&, bool) with the exception that that
+ * method allows to give a custom name for the stream.
+ */
+ static void readINITree(std::istream& in, ParameterTree& pt,
+ bool overwrite);
+
+
+ /** \brief parse C++ stream
+ *
+ * Parses C++ stream and build hierarchical config structure.
+ *
+ * \param in The stream to parse
+ * \param pt The parameter tree to store the config structure.
+ * \param srcname Name of the configuration source for error
+ * messages, "stdin" or a filename.
+ * \param overwrite Whether to overwrite already existing values.
+ * If false, values in the stream will be ignored
+ * if the key is already present.
+ */
+ static void readINITree(std::istream& in, ParameterTree& pt,
+ const std::string srcname = "stream",
+ bool overwrite = true);
+
+
+ /** \brief parse file
+ *
+ * Parses file with given name and build hierarchical config structure.
+ *
+ * \param file filename
+ * \param pt The parameter tree to store the config structure.
+ * \param overwrite Whether to overwrite already existing values.
+ * If false, values in the stream will be ignored
+ * if the key is already present.
+ */
+ static void readINITree(std::string file, ParameterTree& pt, bool overwrite = true);
+
+ //@}
+
+ /** \brief parse command line options and build hierarchical ParameterTree structure
+ *
+ * The list of command line options is searched for pairs of the type <kbd>-key value</kbd>
+ * (note the hyphen in front of the key).
+ * For each such pair of options a key-value pair with the corresponding names
+ * is then created in the ParameterTree.
+ *
+ * \param argc arg count
+ * \param argv arg values
+ * \param pt The parameter tree to store the config structure.
+ */
+ static void readOptions(int argc, char* argv [], ParameterTree& pt);
+
+ };
+
+} // end namespace Dune
+
+#endif // DUNE_PARAMETER_PARSER_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <algorithm>
+#include <iterator>
+#include <string>
+
+#include <dune/common/exceptions.hh>
+#include <dune/common/stringutility.hh>
+#include <dune/common/path.hh>
+
+namespace Dune {
+ /**
+ * @addtogroup Path Filesystem Paths
+ * @ingroup Common
+ * @{
+ */
+
+ /**
+ * @file
+ * @author Jö Fahlke <jorrit@jorrit.de>
+ * @brief Utilites for handling filesystem paths
+ */
+
+ //! concatenate two paths
+ std::string concatPaths(const std::string& base, const std::string& p) {
+ if(p == "") return base;
+ if(p[0] == '/') return p;
+ if(base == "") return p;
+ if(hasSuffix(base, "/")) return base+p;
+ else return base+'/'+p;
+ }
+
+ //! sanitize a path for further processing
+ std::string processPath(const std::string& p) {
+ std::string result = p;
+ std::string::size_type src, dst;
+
+ // append a '/' to non-empty paths
+ if(result != "") result += '/';
+
+ // each path component now has a trailing '/'
+
+ // collapse any occurance of multiple '/' to a single '/'
+ dst = src = 0;
+ while(src < result.size()) {
+ result[dst] = result[src];
+ ++src;
+ if(result[dst] == '/')
+ while(src < result.size() && result[src] == '/')
+ ++src;
+ ++dst;
+ }
+ result.resize(dst);
+
+ // the path is now free of multiple '/' in a row
+
+ // collapse any occurance of "/./" to "/"
+ dst = src = 0;
+ while(src < result.size()) {
+ result[dst] = result[src];
+ ++src;
+ if(result[dst] == '/')
+ while(src+1 < result.size() && result[src] == '.' &&
+ result[src+1] == '/')
+ src+=2;
+ ++dst;
+ }
+ result.resize(dst);
+
+ // there may be at most one leading "./". If so, remove it
+ if(hasPrefix(result, "./")) result.erase(0, 2);
+
+ // the path is now free of "."-components
+
+ // remove any "<component>/../" pairs
+ src = 0;
+ while(true) {
+ src = result.find("/../", src);
+ if(src == std::string::npos)
+ break;
+ for(dst = src; dst > 0 && result[dst-1] != '/'; --dst) ;
+ if(result.substr(dst, src-dst) == "..") {
+ // don't remove "../../"
+ src += 3;
+ continue;
+ }
+ if(dst == src)
+ // special case: "<component>" is the empty component. This means we
+ // found a leading "/../" in an absolute path, remove "/.."
+ result.erase(0, 3);
+ else {
+ // remove "<component>/../".
+ result.erase(dst, src-dst+4);
+ src = dst;
+ // try to back up one character so we are at a '/' instead of at the
+ // beginning of a component
+ if(src > 0) --src;
+ }
+ }
+
+ // absolute paths are now free of ".." components, and relative paths
+ // contain only leading ".." components
+
+ return result;
+ }
+
+ //! check whether the given path indicates that it is a directory
+ bool pathIndicatesDirectory(const std::string& p) {
+ if(p == "") return true;
+ if(p == ".") return true;
+ if(p == "..") return true;
+ if(hasSuffix(p, "/")) return true;
+ if(hasSuffix(p, "/.")) return true;
+ if(hasSuffix(p, "/..")) return true;
+ else return false;
+ }
+
+ //! pretty print path
+ std::string prettyPath(const std::string& p, bool isDirectory) {
+ std::string result = processPath(p);
+ // current directory
+ if(result == "") return ".";
+ // root directory
+ if(result == "/") return result;
+
+ // remove the trailing '/' for now
+ result.resize(result.size()-1);
+
+ // if the result ends in "..", we don't need to append '/' to make clear
+ // it's a directory
+ if(result == ".." || hasSuffix(result, "/.."))
+ return result;
+
+ // if it's a directory, tuck the '/' back on
+ if(isDirectory) result += '/';
+
+ return result;
+ }
+
+ //! pretty print path
+ std::string prettyPath(const std::string& p) {
+ return prettyPath(p, pathIndicatesDirectory(p));
+ }
+
+ //! compute a relative path between two paths
+ std::string relativePath(const std::string& newbase, const std::string& p)
+ {
+ bool absbase = hasPrefix(newbase, "/");
+ bool absp = hasPrefix(p, "/");
+ if(absbase != absp)
+ DUNE_THROW(NotImplemented, "relativePath: paths must be either both "
+ "relative or both absolute: newbase=\"" << newbase << "\" "
+ "p=\"" << p << "\"");
+
+ std::string mybase = processPath(newbase);
+ std::string myp = processPath(p);
+
+ // remove as many matching leading components as possible
+ // determine prefix length
+ std::string::size_type preflen = 0;
+ while(preflen < mybase.size() && preflen < myp.size() &&
+ mybase[preflen] == myp[preflen])
+ ++preflen;
+ // backup to the beginning of the component
+ while(preflen > 0 && myp[preflen-1] != '/')
+ --preflen;
+ mybase.erase(0, preflen);
+ myp.erase(0,preflen);
+
+ // if mybase contains leading ".." components, we're screwed
+ if(hasPrefix(mybase, "../"))
+ DUNE_THROW(NotImplemented, "relativePath: newbase has too many leading "
+ "\"..\" components: newbase=\"" << newbase << "\" "
+ "p=\"" << p << "\"");
+
+ // count the number of components in mybase
+ typedef std::iterator_traits<std::string::iterator>::difference_type
+ count_t;
+ count_t count = std::count(mybase.begin(), mybase.end(), '/');
+
+ std::string result;
+ // prefix with that many leading components
+ for(count_t i = 0; i < count; ++i)
+ result += "../";
+ // append what is left of p
+ result += myp;
+
+ return result;
+ }
+
+ /** @} group Path */
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_COMMON_PATH_HH
+#define DUNE_COMMON_PATH_HH
+
+#include <string>
+
+namespace Dune {
+ /**
+ * @addtogroup Path Filesystem Paths
+ * @ingroup Common
+ * @{
+ */
+
+ /**
+ * @file
+ * @author Jö Fahlke <jorrit@jorrit.de>
+ * @brief Utilities for handling filesystem paths
+ */
+
+ //! concatenate two paths
+ /**
+ * \param base The base path.
+ * \param p The path to concatenate onto base.
+ *
+ * If p is an absolute path, return p. Otherwise return the
+ * string-concatenation of base and path, possibly with a '/' inbetween, if
+ * necessary.
+ *
+ * Some examples:
+ * <table>
+ * <tr><th> base </th><th> p </th><th> result </th></tr>
+ * <tr><td> anything </td><td> "/abs/path" </td><td> "/abs/path" </td></tr>
+ * <tr><td> "a" </td><td> "b" </td><td> "a/b" </td></tr>
+ * <tr><td> "/a" </td><td> "b" </td><td> "/a/b" </td></tr>
+ * <tr><td> "a/" </td><td> "b" </td><td> "a/b" </td></tr>
+ * <tr><td> "a" </td><td> "b/" </td><td> "a/b/" </td></tr>
+ * <tr><td> ".." </td><td> "b" </td><td> "../b" </td></tr>
+ * <tr><td> "a" </td><td> ".." </td><td> "a/.." </td></tr>
+ * <tr><td> "." </td><td> "b" </td><td> "./b" </td></tr>
+ * <tr><td> "a" </td><td> "." </td><td> "a/." </td></tr>
+ * <tr><td> "" </td><td> "b" </td><td> "b" </td></tr>
+ * <tr><td> "a" </td><td> "" </td><td> "a" </td></tr>
+ * <tr><td> "" </td><td> "" </td><td> "" </td></tr>
+ * </table>
+ *
+ * If both base and p are sanitized as per processPath(), and if p does not
+ * contain any leading "../", then the result will also be sanitized.
+ */
+ std::string concatPaths(const std::string& base, const std::string& p);
+
+ //! sanitize a path for further processing
+ /**
+ * Sanitize the path as far as possible to make further processing easier.
+ * The resulting path has the following properties:
+ * <ul>
+ * <li> The path is a series of components, each followed by a single '/'.
+ * <li> An absolute path starts with an empty component followed by a '/',
+ * so its first charachter will be '/'. This is the only case where an
+ * empty component can occur.
+ * <li> The path does not contain any component ".". Any such component in
+ * the input is removed.
+ * <li> A ".." component may only occur in the following case: A relative
+ * path may contain a series of ".." in the beginning. Any other
+ * occurances of ".." int eh input is collapsed with a preceding
+ * component or simply removed if it is at the beginning of an absolute
+ * path.
+ * </ul>
+ *
+ * \note The result is really meant for processing only since it has two
+ * unusual properties: First, any path denoting the current directory
+ * in the input, such as "." will result in an empty path "". Second,
+ * any non-empty result path will have a trailing '/'. For other
+ * uses, prettyPath() may be more appropriate.
+ *
+ * Some examples:
+ * <table>
+ * <tr><th> p </th><th> result </th></tr>
+ * <tr><td> "" </td><td> "" </td></tr>
+ * <tr><td> "." </td><td> "" </td></tr>
+ * <tr><td> "./" </td><td> "" </td></tr>
+ * <tr><td> "a/.." </td><td> "" </td></tr>
+ * <tr><td> ".." </td><td> "../" </td></tr>
+ * <tr><td> "../a" </td><td> "../a/" </td></tr>
+ * <tr><td> "a" </td><td> "a/" </td></tr>
+ * <tr><td> "a//" </td><td> "a/" </td></tr>
+ * <tr><td> "a///b" </td><td> "a/b/" </td></tr>
+ * <tr><td> "/" </td><td> "/" </td></tr>
+ * <tr><td> "/." </td><td> "/" </td></tr>
+ * <tr><td> "/.." </td><td> "/" </td></tr>
+ * <tr><td> "/a/.." </td><td> "/" </td></tr>
+ * <tr><td> "/a" </td><td> "/a/" </td></tr>
+ * <tr><td> "/a/" </td><td> "/a/" </td></tr>
+ * <tr><td> "/../a/" </td><td> "/a/" </td></tr>
+ * </table>
+ */
+ std::string processPath(const std::string& p);
+
+ //! check whether the given path indicates that it is a directory
+ /**
+ * In particular the following kinds of paths indicate a directory:
+ * <ul>
+ * <li> The empty path (denotes the current directory),
+ * <li> any path with a trailing '/',
+ * <li> any path whose last component is "." or "..".
+ * </ul>
+ */
+ bool pathIndicatesDirectory(const std::string& p);
+
+ //! pretty print path
+ /**
+ * \param p Path to pretty-print.
+ * \param isDirectory Whether to append a '/' to make clear this is a
+ * directory.
+ *
+ * Pretty print the path. This removes any duplicate '/' and any
+ * superfluous occurances of ".." and ".". The resulting path will have a
+ * trailing '/' if it is the root path or if isDirectory is true. It will
+ * however not have a trailing '/' if it is otherwise clear that it is a
+ * directory -- i.e. if its last component is "." or "..".
+ *
+ * Some examples:
+ * <table>
+ * <tr><th> p </th><th> isDirectory </th><th> result </th></tr>
+ * <tr><td> "" </td><td> anything </td><td> "." </td></tr>
+ * <tr><td> "." </td><td> anything </td><td> "." </td></tr>
+ * <tr><td> "./" </td><td> anything </td><td> "." </td></tr>
+ * <tr><td> "a/.." </td><td> anything </td><td> "." </td></tr>
+ * <tr><td> ".." </td><td> anything </td><td> ".." </td></tr>
+ * <tr><td> "../a" </td><td> true </td><td> "../a/" </td></tr>
+ * <tr><td> "../a" </td><td> false </td><td> "../a" </td></tr>
+ * <tr><td> "a" </td><td> true </td><td> "a/" </td></tr>
+ * <tr><td> "a" </td><td> false </td><td> "a" </td></tr>
+ * <tr><td> "a//" </td><td> true </td><td> "a/" </td></tr>
+ * <tr><td> "a//" </td><td> false </td><td> "a" </td></tr>
+ * <tr><td> "a///b" </td><td> true </td><td> "a/b/" </td></tr>
+ * <tr><td> "a///b" </td><td> false </td><td> "a/b" </td></tr>
+ * <tr><td> "/" </td><td> anything </td><td> "/" </td></tr>
+ * <tr><td> "/." </td><td> anything </td><td> "/" </td></tr>
+ * <tr><td> "/.." </td><td> anything </td><td> "/" </td></tr>
+ * <tr><td> "/a/.." </td><td> anything </td><td> "/" </td></tr>
+ * <tr><td> "/a" </td><td> true </td><td> "/a/" </td></tr>
+ * <tr><td> "/a" </td><td> false </td><td> "/a" </td></tr>
+ * <tr><td> "/a/" </td><td> true </td><td> "/a/" </td></tr>
+ * <tr><td> "/a/" </td><td> false </td><td> "/a" </td></tr>
+ * <tr><td> "/../a/" </td><td> true </td><td> "/a/" </td></tr>
+ * <tr><td> "/../a/" </td><td> false </td><td> "/a" </td></tr>
+ * </table>
+ */
+ std::string prettyPath(const std::string& p, bool isDirectory);
+
+ //! pretty print path
+ /**
+ * \param p Path to pretty-print.
+ *
+ * This is like prettyPath(const std::string& p, bool isDirectory) with
+ * isDirectory automatically determined using pathIndicatesDirectory(p).
+ */
+ std::string prettyPath(const std::string& p);
+
+ //! compute a relative path between two paths
+ /**
+ * \param newbase Base path for the resulting relative path.
+ * \param p Path re sulting path should resolve to, when taken
+ * reltively to newbase.
+ *
+ * Compute a relative path from newbase to p. newbase is assumed to be a
+ * directory. p and newbase should either both be absolute, or both be
+ * relative. In the latter case they are assumed to both be relative to
+ * the same unspecified directory. The has the form of something sanitized
+ * by processPath().
+ *
+ * \throw NotImplemented The condition that newbase and p must both be
+ * relative or both be absolute does not hold.
+ * \throw NotImplemented After sanitization newbase has more leading ".."
+ * components than p.
+ */
+ std::string relativePath(const std::string& newbase, const std::string& p);
+
+ /** @} group Path */
+}
+
+#endif // DUNE_COMMON_PATH_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+#ifndef DUNE_COMMON_POOLALLOCATOR_HH
+#define DUNE_COMMON_POOLALLOCATOR_HH
+
+/** \file
+ * \brief An stl-compliant pool allocator
+ */
+
+#include "alignment.hh"
+#include "static_assert.hh"
+#include "lcm.hh"
+#include <typeinfo>
+#include <iostream>
+#include <cassert>
+#include <new>
+
+//forward declarations.
+
+// we need to know the test function to declare it friend
+template<std::size_t size, typename T>
+struct testPoolMain;
+
+namespace Dune
+{
+
+ template<typename T, std::size_t s>
+ class Pool;
+
+ template<typename T, std::size_t s>
+ class PoolAllocator;
+
+}
+
+namespace std
+{
+ /*
+ template<class T, std::size_t S>
+ inline ostream& operator<<(ostream& os, Dune::Pool<T,S>& pool)
+ {
+ os<<"pool="<<&pool<<" allocated_="<<pool.allocated_;
+ return os;
+ }
+
+ template<class T, std::size_t S>
+ inline ostream& operator<<(ostream& os, Dune::PoolAllocator<T,S>& pool)
+ {
+ os<<pool.memoryPool_<<std::endl;
+ return os;
+ }
+ */
+}
+
+
+namespace Dune
+{
+ /**
+ * @file
+ * This file implements the classes Pool and PoolAllocator providing
+ * memory allocation for objects in chunks.
+ * @author Markus Blatt
+ */
+ /**
+ * @addtogroup Allocators
+ *
+ * @{
+ */
+
+ /**
+ * @brief A memory pool of objects.
+ *
+ * The memory for the objects is organized in chunks.
+ * Each chunks is capable of holding a specified number of
+ * objects. The allocated objects will be properly aligned
+ * for fast access.
+ * Deallocated objects are cached for reuse to prevent memory
+ * fragmentation.
+ * @warning If the size of the objects allocated is less than the
+ * size of a pointer memory is wasted.
+ * @warning Due to aligned issues at the number of bytes of the
+ * alignment prerequisite (< 4 bytes) are wasted. This effect
+ * becomes negligible for big sizes of chunkSize.
+ *
+ * \tparam T The type that is allocated by us.
+ * \tparam s The size of a memory chunk in bytes.
+ */
+ template<class T, std::size_t s>
+ class Pool
+ {
+ // make the test function friend
+ friend struct ::testPoolMain<s,T>;
+
+ //friend std::ostream& std::operator<<<>(std::ostream&,Pool<T,s>&);
+ template< class, std::size_t > friend class PoolAllocator;
+
+ private:
+
+ /** @brief Reference to next free element. */
+ struct Reference
+ {
+ Reference *next_;
+ };
+
+ public:
+
+ /** @brief The type of object we allocate memory for. */
+ typedef T MemberType;
+ enum
+ {
+ /**
+ * @brief The size of a union of Reference and MemberType.
+ */
+ unionSize = ((sizeof(MemberType) < sizeof(Reference)) ?
+ sizeof(Reference) : sizeof(MemberType)),
+
+ /**
+ * @brief Size requirement. At least one object has to
+ * stored.
+ */
+ size = ((sizeof(MemberType) <= s && sizeof(Reference) <= s) ?
+ s : unionSize),
+
+ /**
+ * @brief The alignment that suits both the MemberType and
+ * the Reference (i.e. their least common multiple).
+ */
+ alignment = Lcm<AlignmentOf<MemberType>::value,AlignmentOf<Reference>::value>::value,
+
+ /**
+ * @brief The aligned size of the type.
+ *
+ * This size is bigger than sizeof of the type and a multiple of
+ * the alignment requirement.
+ */
+ alignedSize = ((unionSize % alignment == 0) ?
+ unionSize :
+ ((unionSize / alignment + 1) * alignment)),
+
+ /**
+ * @brief The size of each chunk memory chunk.
+ *
+ * Will be adapted to be a multiple of the alignment plus
+ * an offset to handle the case that the pointer to the memory
+ * does not satisfy the alignment requirements.
+ */
+ chunkSize = ((size % alignment == 0) ?
+ size : ((size / alignment + 1)* alignment))
+ + alignment - 1,
+
+ /**
+ * @brief The number of element each chunk can hold.
+ */
+ elements = ((chunkSize - alignment + 1)/ alignedSize)
+ };
+
+ private:
+ /** @brief Chunk of memory managed by the pool. */
+ struct Chunk
+ {
+
+ //friend int testPool<s,T>();
+
+ /** @brief The memory we hold. */
+ char chunk_[chunkSize];
+
+ /**
+ * @brief Adress the first properly aligned
+ * position in the chunk.
+ */
+ char* memory_;
+
+ /** @brief The next element */
+ Chunk *next_;
+
+ /**
+ * @brief Constructor.
+ */
+ Chunk()
+ {
+ // Make sure the alignment is correct!
+ // long long should be 64bit safe!
+ unsigned long long lmemory = reinterpret_cast<unsigned long long>(chunk_);
+ if(lmemory % alignment != 0)
+ lmemory = (lmemory / alignment + 1)
+ * alignment;
+
+ memory_ = reinterpret_cast<char *>(lmemory);
+ }
+ };
+
+ public:
+ /** @brief Constructor. */
+ inline Pool();
+ /** @brief Destructor. */
+ inline ~Pool();
+ /**
+ * @brief Get a new or recycled object
+ * @return A pointer to the object memory.
+ */
+ inline void* allocate();
+ /**
+ * @brief Free an object.
+ * @param o The pointer to memory block of the object.
+ */
+ inline void free(void* o);
+
+ /**
+ * @brief Print elements in pool for debugging.
+ */
+ inline void print(std::ostream& os);
+
+ private:
+
+ // Prevent Copying!
+ Pool(const Pool<MemberType,s>&);
+
+ void operator=(const Pool<MemberType,s>& pool) const;
+ /** @brief Grow our pool.*/
+ inline void grow();
+ /** @brief The first free element. */
+ Reference *head_;
+ /** @brief Our memory chunks. */
+ Chunk *chunks_;
+ /* @brief The number of currently allocated elements. */
+ //size_t allocated_;
+
+ };
+
+ /**
+ * @brief An allocator managing a pool of objects for reuse.
+ *
+ * This allocator is specifically useful for small data types
+ * where new and delete are too expensive.
+ *
+ * It uses a pool of memory chunks where the objects will be allocated.
+ * This means that assuming that N objects fit into memory only every N-th
+ * request for an object will result in memory allocation.
+ *
+ * @warning It is not suitable
+ * for the use in standard containers as it cannot allocate
+ * arrays of arbitrary size
+ *
+ * \tparam T The type that will be allocated.
+ * \tparam s The number of elements to fit into one memory chunk.
+ */
+ template<class T, std::size_t s>
+ class PoolAllocator
+ {
+ //friend std::ostream& std::operator<<<>(std::ostream&,PoolAllocator<T,s>&);
+
+ public:
+ /**
+ * @brief Type of the values we construct and allocate.
+ */
+ typedef T value_type;
+
+ enum
+ {
+ /**
+ * @brief The number of objects to fit into one memory chunk
+ * allocated.
+ */
+ size=s*sizeof(value_type)
+ };
+
+ /**
+ * @brief The pointer type.
+ */
+ typedef T* pointer;
+
+ /**
+ * @brief The constant pointer type.
+ */
+ typedef const T* const_pointer;
+
+ /**
+ * @brief The reference type.
+ */
+ typedef T& reference;
+
+ /**
+ * @brief The constant reference type.
+ */
+ typedef const T& const_reference;
+
+ /**
+ * @brief The size type.
+ */
+ typedef std::size_t size_type;
+
+ /**
+ * @brief The difference_type.
+ */
+ typedef std::ptrdiff_t difference_type;
+
+ /**
+ * @brief Constructor.
+ */
+ inline PoolAllocator();
+
+ /**
+ * @brief Copy Constructor that does not copy the memory pool.
+ */
+ template<typename U, std::size_t u>
+ inline PoolAllocator(const PoolAllocator<U,u>&)
+ {
+ // we allow copying but never copy the pool
+ // to have a clear ownership of allocated pointers.
+ }
+
+ /// \brief Copy constructor that does not copy the memory pool.
+ PoolAllocator(const PoolAllocator&)
+ {
+ // we allow copying but never copy the pool
+ // to have a clear ownership of allocated pointers.
+ // For this behaviour we have to implement
+ // the copy constructor, because the default
+ // one would copy the pool and deallocation
+ // of it would break.
+ }
+ /**
+ * @brief Allocates objects.
+ * @param n The number of objects to allocate. Has to be one!
+ * @param hint Ignored hint.
+ * @return A pointer tp the allocated elements.
+ */
+ inline pointer allocate(std::size_t n, const_pointer hint=0);
+
+ /**
+ * @brief Free objects.
+ *
+ * Does not call the destructor!
+ * @param n The number of objects to free. Has to be one!
+ * @param p Pointer to the first object.
+ */
+ inline void deallocate(pointer p, std::size_t n);
+
+ /**
+ * @brief Construct an object.
+ * @param p Pointer to the object.
+ * @param value The value to initialize it to.
+ */
+ inline void construct(pointer p, const_reference value);
+
+ /**
+ * @brief Destroy an object without freeing memory.
+ * @param p Pointer to the object.
+ */
+ inline void destroy(pointer p);
+
+ /**
+ * @brief Convert a reference to a pointer.
+ */
+ inline pointer address(reference x) const { return &x; }
+
+
+ /**
+ * @brief Convert a reference to a pointer.
+ */
+ inline const_pointer address(const_reference x) const { return &x; }
+
+ /**
+ * @brief Not correctly implemented, yet!
+ */
+ inline int max_size() const throw(){ return 1;}
+
+ /**
+ * @brief Rebind the allocator to another type.
+ */
+ template<class U>
+ struct rebind
+ {
+ typedef PoolAllocator<U,s> other;
+ };
+
+ /** @brief The type of the memory pool we use. */
+ typedef Pool<T,size> PoolType;
+
+ private:
+ /**
+ * @brief The underlying memory pool.
+ */
+ PoolType memoryPool_;
+ };
+
+ // specialization for void
+ template <std::size_t s>
+ class PoolAllocator<void,s>
+ {
+ public:
+ typedef void* pointer;
+ typedef const void* const_pointer;
+ // reference to void members are impossible.
+ typedef void value_type;
+ template <class U> struct rebind
+ {
+ typedef PoolAllocator<U,s> other;
+ };
+ };
+
+
+ template<typename T1, std::size_t t1, typename T2, std::size_t t2>
+ bool operator==(const PoolAllocator<T1,t1>&, const PoolAllocator<T2,t2>&)
+ {
+ return false;
+ }
+
+
+ template<typename T1, std::size_t t1, typename T2, std::size_t t2>
+ bool operator!=(const PoolAllocator<T1,t1>&, const PoolAllocator<T2,t2>&)
+ {
+ return true;
+ }
+
+ template<typename T, std::size_t t1, std::size_t t2>
+ bool operator==(const PoolAllocator<T,t1>& p1, const PoolAllocator<T,t2>& p2)
+ {
+ return &p1==&p2;
+ }
+
+
+ template<typename T, std::size_t t1, std::size_t t2>
+ bool operator!=(const PoolAllocator<T,t1>& p1, const PoolAllocator<T,t2>& p2)
+ {
+ return &p1 != &p2;
+ }
+
+ template<typename T, std::size_t t1, std::size_t t2>
+ bool operator==(const PoolAllocator<void,t1>&, const PoolAllocator<T,t2>&)
+ {
+ return false;
+ }
+
+
+ template<typename T, std::size_t t1, std::size_t t2>
+ bool operator!=(const PoolAllocator<void,t1>&, const PoolAllocator<T,t2>&)
+ {
+ return true;
+ }
+
+ template<std::size_t t1, std::size_t t2>
+ bool operator==(const PoolAllocator<void,t1>& p1, const PoolAllocator<void,t2>& p2)
+ {
+ return &p1==&p2;
+ }
+
+ template<std::size_t t1, std::size_t t2>
+ bool operator!=(const PoolAllocator<void,t1>& p1, const PoolAllocator<void,t2>& p2)
+ {
+ return &p1!=&p2;
+ }
+
+ template<class T, std::size_t S>
+ inline Pool<T,S>::Pool()
+ : head_(0), chunks_(0) //, allocated_(0)
+ {
+ dune_static_assert(sizeof(T)<=unionSize, "Library Error: type T is too big");
+ dune_static_assert(sizeof(Reference)<=unionSize, "Library Error: type of referene is too big");
+ dune_static_assert(unionSize<=alignedSize, "Library Error: alignedSize too small");
+ dune_static_assert(sizeof(T)<=chunkSize, "Library Error: chunkSize must be able to hold at least one value");
+ dune_static_assert(sizeof(Reference)<=chunkSize, "Library Error: chunkSize must be able to hold at least one reference");
+ dune_static_assert((chunkSize - (alignment - 1)) % alignment == 0, "Library Error: compiler cannot calculate!");
+ dune_static_assert(elements>=1, "Library Error: we need to hold at least one element!");
+ dune_static_assert(elements*alignedSize<=chunkSize, "Library Error: aligned elements must fit into chuck!");
+ }
+
+ template<class T, std::size_t S>
+ inline Pool<T,S>::~Pool()
+ {
+ /*
+ if(allocated_!=0)
+ std::cerr<<"There are still "<<allocated_<<" allocated elements by the Pool<"<<typeid(T).name()<<","<<S<<"> "
+ <<static_cast<void*>(this)<<"! This is a memory leak and might result in segfaults"
+ <<std::endl;
+ */
+ // delete the allocated chunks.
+ Chunk *current=chunks_;
+
+ while(current!=0)
+ {
+ Chunk *tmp = current;
+ current = current->next_;
+ delete tmp;
+ }
+ }
+
+ template<class T, std::size_t S>
+ inline void Pool<T,S>::print(std::ostream& os)
+ {
+ Chunk* current=chunks_;
+ while(current) {
+ os<<current<<" ";
+ current=current->next_;
+ }
+ os<<current<<" ";
+ }
+
+ template<class T, std::size_t S>
+ inline void Pool<T,S>::grow()
+ {
+ Chunk *newChunk = new Chunk;
+ newChunk->next_ = chunks_;
+ chunks_ = newChunk;
+
+ char* start = chunks_->memory_;
+ char* last = &start[elements*alignedSize];
+ Reference* ref = new (start) (Reference);
+
+ // grow is only called if head==0,
+ assert(!head_);
+
+ head_ = ref;
+
+ for(char* element=start+alignedSize; element<last; element=element+alignedSize) {
+ Reference* next = new (element) (Reference);
+ ref->next_ = next;
+ ref = next;
+ }
+ ref->next_=0;
+ }
+
+ template<class T, std::size_t S>
+ inline void Pool<T,S>::free(void* b)
+ {
+ if(b) {
+#ifndef NDEBUG
+ Chunk* current=chunks_;
+ while(current) {
+ if(static_cast<void*>(¤t->chunk_)<=b &&
+ static_cast<void*>((¤t->chunk_)+chunkSize)>b)
+ break;
+ current=current->next_;
+ }
+ if(!current)
+ throw std::bad_alloc();
+#endif
+ Reference* freed = static_cast<Reference*>(b);
+ freed->next_ = head_;
+ head_ = freed;
+ //--allocated_;
+ }
+ else
+ {
+ std::cerr<< "Tried to free null pointer! "<<b<<std::endl;
+ throw std::bad_alloc();
+ }
+ }
+
+ template<class T, std::size_t S>
+ inline void* Pool<T,S>::allocate()
+ {
+ if(!head_)
+ grow();
+
+ Reference* p = head_;
+ head_ = p->next_;
+ //++allocated_;
+ return p;
+ }
+
+ template<class T, std::size_t s>
+ inline PoolAllocator<T,s>::PoolAllocator()
+ { }
+
+ template<class T, std::size_t s>
+ inline typename PoolAllocator<T,s>::pointer
+ PoolAllocator<T,s>::allocate(std::size_t n, const_pointer hint)
+ {
+ if(n==1)
+ return static_cast<T*>(memoryPool_.allocate());
+ else
+ throw std::bad_alloc();
+ }
+
+ template<class T, std::size_t s>
+ inline void PoolAllocator<T,s>::deallocate(pointer p, std::size_t n)
+ {
+ for(size_t i=0; i<n; i++)
+ memoryPool_.free(p++);
+ }
+
+ template<class T, std::size_t s>
+ inline void PoolAllocator<T,s>::construct(pointer p, const_reference value)
+ {
+ ::new (static_cast<void*>(p))T(value);
+ }
+
+ template<class T, std::size_t s>
+ inline void PoolAllocator<T,s>::destroy(pointer p)
+ {
+ p->~T();
+ }
+
+ /** @} */
+}
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_COMMON_POWER_HH
+#define DUNE_COMMON_POWER_HH
+
+/** \file
+ \brief Various implementations of the power function for run-time and static arguments
+ */
+
+namespace Dune {
+
+ /** @addtogroup Common
+
+ @{
+ */
+
+ //! Calculates m^p at compile time
+ template <int m, int p>
+ struct StaticPower
+ {
+ /** \brief power stores m^p */
+ enum { power = (m * StaticPower<m,p-1>::power ) };
+ };
+
+ //! end of recursion via specialization
+ template <int m>
+ struct StaticPower< m , 0>
+ {
+ /** \brief m^0 = 1 */
+ enum { power = 1 };
+ };
+
+
+ #ifndef DOXYGEN
+ template <int p, bool odd = p%2>
+ struct PowerImp {};
+#endif
+
+ /** \brief Compute power for a run-time mantissa and a compile-time integer exponent
+ *
+ * Does some magic to create efficient code. Not benchmarked AFAIK.
+ *
+ * \tparam p The exponent
+ */
+ template <int p>
+ struct Power
+ {
+ template <typename T>
+ static T eval(const T & a)
+ {
+ return PowerImp<p>::eval(a);
+ }
+ };
+
+#ifndef DOXYGEN
+ template <int p>
+ struct PowerImp<p,false>
+ {
+ template <typename T>
+ static T eval(const T & a)
+ {
+ T t = Power<p/2>::eval(a);
+ return t*t;
+ }
+ };
+
+ template <int p>
+ struct PowerImp<p,true>
+ {
+ template <typename T>
+ static T eval(const T & a)
+ {
+ return a*Power<p-1>::eval(a);;
+ }
+ };
+
+ template <>
+ struct PowerImp<1,true>
+ {
+ template <typename T>
+ static T eval(const T & a)
+ {
+ return a;
+ }
+ };
+#endif
+
+}
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_PRECISION_HH
+#define DUNE_PRECISION_HH
+
+/** \file
+ * \brief Various precision settings for calculations with FieldMatrix and FieldVector
+ */
+
+#include <stdlib.h>
+
+namespace Dune {
+
+ /**
+ @addtogroup DenseMatVec
+ @{
+ */
+
+ /**
+ * @brief Precisions for calculations with FieldMatrix and FieldVector.
+ */
+ template <class ctype = double>
+ class FMatrixPrecision {
+ public:
+ //! return threshold to do pivoting
+ static ctype pivoting_limit ()
+ {
+ return _pivoting;
+ }
+
+ //! set pivoting threshold
+ static void set_pivoting_limit (ctype pivthres)
+ {
+ _pivoting = pivthres;
+ }
+
+ //! return threshold to declare matrix singular
+ static ctype singular_limit ()
+ {
+ return _singular;
+ }
+
+ //! set singular threshold
+ static void set_singular_limit (ctype singthres)
+ {
+ _singular = singthres;
+ }
+
+ //! return threshold to declare matrix singular
+ static ctype absolute_limit ()
+ {
+ return _absolute;
+ }
+
+ //! set singular threshold
+ static void set_absolute_limit (ctype absthres)
+ {
+ _absolute = absthres;
+ }
+
+ private:
+ // just to demonstrate some state information
+ static ctype _pivoting;
+ static ctype _singular;
+ static ctype _absolute;
+ };
+
+ template <class ctype>
+ ctype FMatrixPrecision<ctype>::_pivoting = 1E-8;
+ template <class ctype>
+ ctype FMatrixPrecision<ctype>::_singular = 1E-14;
+ template <class ctype>
+ ctype FMatrixPrecision<ctype>::_absolute = 1E-80;
+
+ /** @} end documentation */
+
+} // end namespace
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_PROMOTIONTRAITS_HH
+#define DUNE_PROMOTIONTRAITS_HH
+
+#include <complex>
+
+namespace Dune {
+ /**
+ * @file
+ * @brief Provides some promotion traits
+ *
+ * For example, the promotion traits are used for the implementation of dot products @see <dune/common/dotproduct.hh>
+ * @author Matthias Wohlmuth
+ */
+
+ /** @addtogroup Common
+ *
+ * @{
+ */
+
+ /**
+ ** \brief Class for type promotions. For example, the promotion traits are used for the implementation of dot products @see <dune/common/dotproduct.hh>
+ ** \private basic template:
+ */
+ template <typename T1, typename T2>
+ struct PromotionTraits { };
+
+#ifndef DOXYGEN
+ // class for type promotion; // the same types are the same:
+ template <typename T1>
+ struct PromotionTraits<T1,T1> { typedef T1 PromotedType; };
+
+ // promote to complex type
+ template <typename T1>
+ struct PromotionTraits<std::complex<T1>,T1> { typedef std::complex<T1> PromotedType; };
+
+ // \private promote to complex type
+ template <typename T1>
+ struct PromotionTraits<T1,std::complex<T1> > { typedef std::complex<T1> PromotedType; };
+
+ // a few specializations for some common cases
+ template<> struct PromotionTraits<std::complex<double>,std::complex<double> > { typedef std::complex<double> PromotedType; };
+ template<> struct PromotionTraits<std::complex<double>,double> { typedef std::complex<double> PromotedType; };
+ template<> struct PromotionTraits<double,std::complex<double> > { typedef std::complex<double> PromotedType; };
+ template<> struct PromotionTraits<double,double> { typedef double PromotedType; };
+
+ template<> struct PromotionTraits<std::complex<float>,float> { typedef std::complex<float> PromotedType; };
+ template<> struct PromotionTraits<float,std::complex<float> > { typedef std::complex<float> PromotedType; };
+ template<> struct PromotionTraits<std::complex<float>,std::complex<float> > { typedef std::complex<float> PromotedType; };
+ template<> struct PromotionTraits<float,float> { typedef float PromotedType; };
+
+ template<> struct PromotionTraits<std::complex<int>,int> { typedef std::complex<int> PromotedType; };
+ template<> struct PromotionTraits<int,std::complex<int> > { typedef std::complex<int> PromotedType; };
+ template<> struct PromotionTraits<std::complex<int>,std::complex<int> > { typedef std::complex<int> PromotedType; };
+ template<> struct PromotionTraits<int,int> { typedef int PromotedType; };
+#endif // DOXYGEN
+
+ /** @} */
+} // end namespace
+
+
+#endif // DUNE_PROMOTIONTRAITS_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+#ifndef DUNE_PROPERTYMAP_HH
+#define DUNE_PROPERTYMAP_HH
+
+#include <cstddef>
+#include <iterator>
+
+#include "static_assert.hh"
+#include "typetraits.hh"
+
+namespace Dune
+{
+
+ template<class PM>
+ struct PropertyMapTraits
+ {
+ /**
+ * @brief The type of the key of the property map.
+ */
+ typedef typename PM::KeyType KeyType;
+ /**
+ * @brief The type of the values of the property map.
+ */
+ typedef typename PM::ValueType ValueType;
+ /**
+ * @brief The type of the reference to the values.
+ */
+ typedef typename PM::Reference Reference;
+ /**
+ * @brief The category the property map belongs to.
+ */
+ typedef typename PM::Category Category;
+ };
+
+ /** @brief Tag for the category of readable property maps. */
+ struct ReadablePropertyMapTag
+ {};
+
+ /** @brief Tag for the category of writable property maps. */
+ struct WritablePropertyMapTag
+ {};
+
+ /**
+ * @brief Tag for the category of readable and writable property
+ * maps.
+ */
+ struct ReadWritePropertyMapTag
+ : public ReadablePropertyMapTag, public WritablePropertyMapTag
+ {};
+
+ /**
+ * @brief Tag for the category of lvalue property maps.
+ */
+ struct LvaluePropertyMapTag
+ : public ReadWritePropertyMapTag
+ {};
+
+ template<class T>
+ struct PropertyMapTraits<T*>
+ {
+ typedef T ValueType;
+ typedef ValueType& Reference;
+ typedef std::ptrdiff_t KeyType;
+ typedef LvaluePropertyMapTag Category;
+ };
+
+
+ template<class T>
+ struct PropertyMapTraits<const T*>
+ {
+ typedef T ValueType;
+ typedef const ValueType& Reference;
+ typedef std::ptrdiff_t KeyType;
+ typedef LvaluePropertyMapTag Category;
+ };
+
+ template<class Reference, class PropertyMap>
+ struct RAPropertyMapHelper
+ {};
+
+ template<class Reference, class PropertyMap, class Key>
+ inline Reference
+ get(const RAPropertyMapHelper<Reference,PropertyMap>& pmap,
+ const Key& key)
+ {
+ return static_cast<const PropertyMap&>(pmap)[key];
+ }
+
+ template<class Reference, class PropertyMap, class Key, class Value>
+ inline void
+ put(const RAPropertyMapHelper<Reference,PropertyMap>& pmap,
+ const Key& key, const Value& value)
+ {
+ dune_static_assert((Conversion<typename PropertyMap::Category,WritablePropertyMapTag>
+ ::exists), "WritablePropertyMapTag required!");
+ static_cast<const PropertyMap&>(pmap)[key] = value;
+ }
+
+ /**
+ * @brief Adapter to turn a random access iterator into a property map.
+ */
+ template<class RAI, class IM,
+ class T = typename std::iterator_traits<RAI>::value_type,
+ class R = typename std::iterator_traits<RAI>::reference>
+ class IteratorPropertyMap
+ : public RAPropertyMapHelper<R,IteratorPropertyMap<RAI,IM,T,R> >
+ {
+ public:
+ /**
+ * @brief The type of the random access iterator.
+ */
+ typedef RAI RandomAccessIterator;
+
+ /**
+ * @brief The type of the index map.
+ *
+ * This will convert the KeyType to std::ptrdiff_t via operator[]().
+ */
+ typedef IM IndexMap;
+
+ /**
+ * @brief The key type of the property map.
+ */
+ typedef typename IndexMap::KeyType KeyType;
+
+ /**
+ * @brief The value type of the property map.
+ */
+ typedef T ValueType;
+
+ /**
+ * @brief The reference type of the property map.
+ */
+ typedef R Reference;
+
+ /**
+ * @brief The category of this property map.
+ */
+ typedef LvaluePropertyMapTag Category;
+
+ /**
+ * @brief Constructor.
+ * @param iter The random access iterator that
+ * provides the mapping.
+ * @param im The index map that maps the KeyType
+ * to the difference_type of the iterator.
+ */
+ inline IteratorPropertyMap(RandomAccessIterator iter,
+ const IndexMap& im=IndexMap())
+ : iter_(iter), indexMap_(im)
+ {}
+
+ /** @brief Constructor. */
+ inline IteratorPropertyMap()
+ : iter_(), indexMap_()
+ {}
+
+ /** @brief Access the a value by reference. */
+ inline Reference operator[](KeyType key) const
+ {
+ return *(iter_ + get(indexMap_, key));
+ }
+
+ private:
+ /** @brief The underlying iterator. */
+ RandomAccessIterator iter_;
+ /** @brief The index map to use for the lookup. */
+ IndexMap indexMap_;
+ };
+
+ /**
+ * @brief An adapter to turn an unique associative container
+ * into a property map.
+ */
+ template<typename T>
+ class AssociativePropertyMap
+ : RAPropertyMapHelper<typename T::value_type::second_type&,
+ AssociativePropertyMap<T> >
+ {
+ /**
+ * @brief The type of the unique associative container.
+ */
+ typedef T UniqueAssociativeContainer;
+
+ /**
+ * @brief The key type of the property map.
+ */
+ typedef typename UniqueAssociativeContainer::value_type::first_type
+ KeyType;
+
+ /**
+ * @brief The value type of the property map.
+ */
+ typedef typename UniqueAssociativeContainer::value_type::second_type
+ ValueType;
+
+ /**
+ * @brief The reference type of the property map.
+ */
+ typedef ValueType& Reference;
+
+ /**
+ * @brief The category of the property map.
+ */
+ typedef LvaluePropertyMapTag Category;
+
+ /** @brief Constructor */
+ inline AssociativePropertyMap()
+ : map_(0)
+ {}
+
+ /** @brief Constructor. */
+ inline AssociativePropertyMap(UniqueAssociativeContainer& map)
+ : map_(&map)
+ {}
+
+ /**
+ * @brief Access a property.
+ * @param key The key of the property.
+ */
+ inline Reference operator[](KeyType key) const
+ {
+ return map_->find(key)->second;
+ }
+ private:
+ UniqueAssociativeContainer* map_;
+ };
+
+ /**
+ * @brief An adaptor to turn an unique associative container
+ * into a property map.
+ */
+ template<typename T>
+ class ConstAssociativePropertyMap
+ : RAPropertyMapHelper<const typename T::value_type::second_type&,
+ ConstAssociativePropertyMap<T> >
+ {
+ /**
+ * @brief The type of the unique associative container.
+ */
+ typedef T UniqueAssociativeContainer;
+
+ /**
+ * @brief The key type of the property map.
+ */
+ typedef typename UniqueAssociativeContainer::value_type::first_type
+ KeyType;
+
+ /**
+ * @brief The value type of the property map.
+ */
+ typedef typename UniqueAssociativeContainer::value_type::second_type
+ ValueType;
+
+ /**
+ * @brief The reference type of the property map.
+ */
+ typedef const ValueType& Reference;
+
+ /**
+ * @brief The category of the property map.
+ */
+ typedef LvaluePropertyMapTag Category;
+
+ /** @brief Constructor */
+ inline ConstAssociativePropertyMap()
+ : map_(0)
+ {}
+
+ /** @brief Constructor. */
+ inline ConstAssociativePropertyMap(const UniqueAssociativeContainer& map)
+ : map_(&map)
+ {}
+
+ /**
+ * @brief Access a property.
+ * @param key The key of the property.
+ */
+ inline Reference operator[](KeyType key) const
+ {
+ return map_->find(key)->second;
+ }
+ private:
+ const UniqueAssociativeContainer* map_;
+ };
+
+ /**
+ * @brief A property map that applies the identity function to integers.
+ */
+ struct IdentityMap
+ : public RAPropertyMapHelper<std::size_t, IdentityMap>
+ {
+ /** @brief The key type of the map. */
+ typedef std::size_t KeyType;
+
+ /** @brief The value type of the map. */
+ typedef std::size_t ValueType;
+
+ /** @brief The reference type of the map. */
+ typedef std::size_t Reference;
+
+ /** @brief The category of the map. */
+ typedef ReadablePropertyMapTag Category;
+
+ inline ValueType operator[](const KeyType& key) const
+ {
+ return key;
+ }
+ };
+
+
+ /**
+ * @brief Selector for the property map type.
+ *
+ * If present the type of the property map is accessible via the typedef Type.
+ */
+ template<typename T, typename C>
+ struct PropertyMapTypeSelector
+ {
+ /**
+ * @brief the tag identifying the property.
+ */
+ typedef T Tag;
+ /**
+ * @brief The container type to whose entries the properties
+ * are attached.
+ */
+ typedef C Container;
+ };
+
+}
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef RESERVEDVECTOR_HH
+#define RESERVEDVECTOR_HH
+
+/** \file
+ * \brief An stl-compliant random-access container which stores everything on the stack
+ */
+
+#include <iostream>
+#include <dune/common/genericiterator.hh>
+
+#ifdef CHECK_RESERVEDVECTOR
+#define CHECKSIZE(X) assert(X)
+#else
+#define CHECKSIZE(X) {}
+#endif
+
+namespace Dune
+{
+ /**
+ \brief A Vector class with statically reserved memory.
+
+ ReservedVector is something between Dune::array and std::vector.
+ You have vector which can be extended and shrunk using methods like
+ push_back and pop_back, but reserved memory is predefined.
+
+ This implies that the vector can not grow bigger than the predefined
+ maximum size.
+
+ \tparam T The data type ReservedVector stores.
+ \tparam n The maximum number of objects the ReservedVector can store.
+
+ */
+ template<class T, int n>
+ class ReservedVector
+ {
+ public:
+
+ /** @{ Typedefs */
+
+ //! The type of object, T, stored in the vector.
+ typedef T value_type;
+ //! Pointer to T.
+ typedef T* pointer;
+ //! Reference to T
+ typedef T& reference;
+ //! Const reference to T
+ typedef const T& const_reference;
+ //! An unsigned integral type.
+ typedef size_t size_type;
+ //! A signed integral type.
+ typedef std::ptrdiff_t difference_type;
+ //! Iterator used to iterate through a vector.
+ typedef Dune::GenericIterator<ReservedVector, value_type> iterator;
+ //! Const iterator used to iterate through a vector.
+ typedef Dune::GenericIterator<const ReservedVector, const value_type> const_iterator;
+
+ /** @} */
+
+ /** @{ Constructors */
+
+ //! Constructor
+ ReservedVector() : sz(0) {}
+
+ /** @} */
+
+ /** @{ Data access operations */
+
+ //! Erases all elements.
+ void clear()
+ {
+ sz = 0;
+ }
+
+ //! Specifies a new size for the vector.
+ void resize(size_t s)
+ {
+ CHECKSIZE(s<=n);
+ sz = s;
+ }
+
+ //! Appends an element to the end of a vector, up to the maximum size n, O(1) time.
+ void push_back(const T& t)
+ {
+ CHECKSIZE(sz<n);
+ data[sz++] = t;
+ }
+
+ //! Erases the last element of the vector, O(1) time.
+ void pop_back()
+ {
+ if (! empty()) sz--;
+ }
+
+ //! Returns a iterator pointing to the beginning of the vector.
+ iterator begin(){
+ return iterator(*this, 0);
+ }
+
+ //! Returns a const_iterator pointing to the beginning of the vector.
+ const_iterator begin() const {
+ return const_iterator(*this, 0);
+ }
+
+ //! Returns an iterator pointing to the end of the vector.
+ iterator end(){
+ return iterator(*this, sz);
+ }
+
+ //! Returns a const_iterator pointing to the end of the vector.
+ const_iterator end() const {
+ return const_iterator(*this, sz);
+ }
+
+ //! Returns reference to the i'th element.
+ reference operator[] (size_type i)
+ {
+ CHECKSIZE(sz>i);
+ return data[i];
+ }
+
+ //! Returns a const reference to the i'th element.
+ const_reference operator[] (size_type i) const
+ {
+ CHECKSIZE(sz>i);
+ return data[i];
+ }
+
+ //! Returns reference to first element of vector.
+ reference front()
+ {
+ CHECKSIZE(sz>0);
+ return data[0];
+ }
+
+ //! Returns const reference to first element of vector.
+ const_reference front() const
+ {
+ CHECKSIZE(sz>0);
+ return data[0];
+ }
+
+ //! Returns reference to last element of vector.
+ reference back()
+ {
+ CHECKSIZE(sz>0);
+ return data[sz-1];
+ }
+
+ //! Returns const reference to last element of vector.
+ const_reference back() const
+ {
+ CHECKSIZE(sz>0);
+ return data[sz-1];
+ }
+
+ /** @} */
+
+ /** @{ Informative Methods */
+
+ //! Returns number of elements in the vector.
+ size_type size () const
+ {
+ return sz;
+ }
+
+ //! Returns true if vector has no elements.
+ bool empty() const
+ {
+ return sz==0;
+ }
+
+ //! Returns current capacity (allocated memory) of the vector.
+ static size_type capacity()
+ {
+ return n;
+ }
+
+ //! Returns the maximum length of the vector.
+ static size_type max_size()
+ {
+ return n;
+ }
+
+ /** @} */
+
+ //! Send ReservedVector to an output stream
+ friend std::ostream& operator<< (std::ostream& s, const ReservedVector& v)
+ {
+ for (size_t i=0; i<v.size(); i++)
+ s << v[i] << " ";
+ return s;
+ }
+
+ private:
+ T data[n];
+ size_type sz;
+ };
+
+}
+
+#undef CHECKSIZE
+
+#endif // RESERVEDVECTOR_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id: smartpointer.hh 5504 2009-04-08 13:35:31Z christi $
+
+#ifndef DUNE_SHARED_PTR_HH
+#define DUNE_SHARED_PTR_HH
+
+#if defined SHARED_PTR_HEADER
+# include SHARED_PTR_HEADER
+#endif
+#if defined HAVE_BOOST_SHARED_PTR_HPP
+#if defined HAVE_BOOST_MAKE_SHARED_HPP
+# include <boost/make_shared.hpp>
+#endif
+#endif
+
+#include <dune/common/nullptr.hh>
+#include <dune/common/typetraits.hh>
+/**
+ * @file
+ * @brief This file implements the class shared_ptr (a reference counting
+ * pointer), for those systems that don't have it in the standard library.
+ * @author Markus Blatt
+ */
+namespace Dune
+{
+ // A shared_ptr implementation has been found if SHARED_PTR_NAMESPACE is set at all
+#ifdef SHARED_PTR_NAMESPACE
+ using SHARED_PTR_NAMESPACE :: shared_ptr;
+#else
+
+ /** @addtogroup Common
+ *
+ * @{
+ */
+
+ /** @brief The object we reference. */
+ class SharedCount
+ {
+ template<class T1>
+ friend class shared_ptr;
+ protected:
+ /** @brief The number of references. */
+ int count_;
+ /** @brief Constructor from existing Pointer. */
+ SharedCount() : count_(1) {}
+ /** @brief Copy constructor with type conversion. */
+ SharedCount(const SharedCount& rep)
+ : count_(rep.count_) {}
+
+ /** @brief Destructor, deletes element_type* rep_. */
+ virtual ~SharedCount() {};
+
+ };
+ /**
+ * @brief A reference counting smart pointer.
+ *
+ * It is designed such that it is usable within a std::vector.
+ * The contained object is destroyed only if there are no more
+ * references to it.
+ */
+ template<class T>
+ class shared_ptr
+ {
+ template<class T1> friend class shared_ptr;
+
+ public:
+ /**
+ * @brief The data type we are a pointer for.
+ *
+ * This has to have a parameterless constructor.
+ */
+ typedef T element_type;
+
+ /**
+ * @brief Constructs a new smart pointer and allocates the referenced Object.
+ */
+ inline shared_ptr();
+
+ inline shared_ptr(nullptr_t null);
+
+ /**
+ * @brief Constructs a new smart pointer from a preallocated Object.
+ *
+ * \param pointer Raw pointer to the shared data
+ *
+ * note: the object must be allocated on the heap and after handing the pointer to
+ * shared_ptr the ownership of the pointer is also handed to the shared_ptr.
+ */
+ template<class T1>
+ inline shared_ptr(T1 * pointer);
+
+
+ /**
+ * @brief Constructs a new smart pointer from a preallocated Object.
+ *
+ * \tparam Deleter This class must by copyconstructable, the copy constructor must not throw an exception
+ * and it must implement void operator() (T*) const
+ *
+ * \param pointer Raw pointer to the shared data
+ * \param deleter A copy of this deleter is stored
+ *
+ * note: the object must be allocated on the heap and after handing the pointer to
+ * shared_ptr the ownership of the pointer is also handed to the shared_ptr.
+ */
+ template<class T1, class Deleter>
+ inline shared_ptr(T1 * pointer, Deleter deleter);
+
+ /**
+ * @brief Copy constructor.
+ * @param pointer The object to copy.
+ */
+ template<class T1>
+ inline shared_ptr(const shared_ptr<T1>& pointer);
+
+ /**
+ * @brief Copy constructor.
+ * @param pointer The object to copy.
+ */
+ inline shared_ptr(const shared_ptr& pointer);
+
+ /**
+ * @brief Destructor.
+ */
+ inline ~shared_ptr();
+
+ /** \brief Assignment operator */
+ template<class T1>
+ inline shared_ptr& operator=(const shared_ptr<T1>& pointer);
+
+ /** \brief Assignment operator */
+ inline shared_ptr& operator=(const shared_ptr& pointer);
+
+ /** \brief Dereference as object */
+ inline element_type& operator*();
+
+ /** \brief Dereference as pointer */
+ inline element_type* operator->();
+
+ /** \brief Dereference as const object */
+ inline const element_type& operator*() const;
+
+ /** \brief Dereference as const pointer */
+ inline const element_type* operator->() const;
+
+ /** \brief Access to the raw pointer, if you really want it */
+ element_type* get() const {
+ return rep_;
+ }
+
+ /** \brief Checks if shared_ptr manages an object, i.e. whether get() != 0. */
+ operator bool() const {
+ return count_ != 0 && rep_ != 0;
+ }
+
+ /** \brief Swap content of this shared_ptr and another */
+ inline void swap(shared_ptr& other);
+
+ /** \brief Decrease the reference count by one and free the memory if the
+ reference count has reached 0
+ */
+ inline void reset();
+
+ /** \brief Detach shared pointer and set it anew for the given pointer */
+ template<class T1>
+ inline void reset(T1* pointer);
+
+ //** \brief Same as shared_ptr(pointer,deleter).swap(*this)
+ template<class T1, class Deleter>
+ inline void reset(T1* pointer, Deleter deleter);
+
+ /** \brief The number of shared_ptrs pointing to the object we point to */
+ int use_count() const;
+
+ private:
+ /** \brief Assignment operator */
+ template<class T1>
+ inline shared_ptr& assign(const shared_ptr<T1>& pointer);
+ /** @brief Adds call to deleter to SharedCount. */
+ template<class Deleter>
+ class SharedCountImpl :
+ public SharedCount
+ {
+ template<class T1>
+ friend class shared_ptr;
+ /** @brief Constructor from existing Pointer with custom deleter. */
+ SharedCountImpl(T* elem,const Deleter& deleter) :
+ SharedCount(),
+ deleter_(deleter),
+ rep_(elem)
+ {}
+ /** @brief Copy constructor with type conversion. */
+ SharedCountImpl(const SharedCountImpl& rep)
+ : SharedCount(rep), deleter_(rep.deleter_), rep_(rep.rep_) {}
+ /** @brief Destructor, deletes element_type* rep_ using deleter. */
+ ~SharedCountImpl()
+ { deleter_(rep_); }
+
+ // store a copy of the deleter
+ Deleter deleter_;
+ T* rep_;
+ };
+
+ /** \brief A default deleter that just calls delete */
+ struct DefaultDeleter
+ {
+ void operator() (element_type* p) const
+ { delete p; }
+ };
+
+
+ SharedCount *count_;
+ T *rep_;
+
+ // Needed for the implicit conversion to "bool"
+ typedef T* *__unspecified_bool_type;
+
+ public:
+ /** \brief Implicit conversion to "bool" */
+ operator __unspecified_bool_type() const // never throws
+ {
+ return rep_ == 0 ? 0 : &shared_ptr::rep_;
+ }
+
+ };
+
+ template<class T>
+ template<class T1>
+ inline shared_ptr<T>::shared_ptr(T1 * p)
+ {
+ rep_ = p;
+ count_ = new SharedCountImpl<DefaultDeleter>(p, DefaultDeleter());
+ }
+
+ template<class T>
+ inline shared_ptr<T>::shared_ptr(nullptr_t)
+ {
+ rep_ = 0;
+ count_ = 0;
+ }
+
+ template<class T>
+ template<class T1, class Deleter>
+ inline shared_ptr<T>::shared_ptr(T1 * p, Deleter deleter)
+ {
+ rep_ = p;
+ count_ = new SharedCountImpl<Deleter>(p, deleter);
+ }
+
+ template<class T>
+ inline shared_ptr<T>::shared_ptr()
+ {
+ rep_ = 0;
+ count_=0;
+ }
+
+ template<class T>
+ template<class T1>
+ inline shared_ptr<T>::shared_ptr(const shared_ptr<T1>& other)
+ : count_(other.count_), rep_(other.rep_)
+ {
+ if (rep_)
+ ++(count_->count_);
+ }
+
+ template<class T>
+ inline shared_ptr<T>::shared_ptr(const shared_ptr& other)
+ : count_(other.count_), rep_(other.rep_)
+ {
+ if (rep_)
+ ++(count_->count_);
+ }
+
+ template<class T>
+ template<class T1>
+ inline shared_ptr<T>& shared_ptr<T>::operator=(const shared_ptr<T1>& other)
+ {
+ return assign(other);
+ }
+
+ template<class T>
+ inline shared_ptr<T>& shared_ptr<T>::operator=(const shared_ptr& other)
+ {
+ return assign(other);
+ }
+
+ template<class T>
+ template<class T1>
+ inline shared_ptr<T>& shared_ptr<T>::assign(const shared_ptr<T1>& other)
+ {
+ if (other.count_)
+ (other.count_->count_)++;
+
+ if(rep_!=0 && --(count_->count_)<=0) {
+ delete count_;
+ }
+
+ rep_ = other.rep_;
+ count_ = other.count_;
+ return *this;
+ }
+
+ template<class T>
+ inline shared_ptr<T>::~shared_ptr()
+ {
+ if(rep_!=0 && --(count_->count_)==0) {
+ delete count_;
+ rep_=0;
+ }
+ }
+
+ template<class T>
+ inline T& shared_ptr<T>::operator*()
+ {
+ return *(rep_);
+ }
+
+ template<class T>
+ inline T *shared_ptr<T>::operator->()
+ {
+ return rep_;
+ }
+
+ template<class T>
+ inline const T& shared_ptr<T>::operator*() const
+ {
+ return *(rep_);
+ }
+
+ template<class T>
+ inline const T *shared_ptr<T>::operator->() const
+ {
+ return rep_;
+ }
+
+ template<class T>
+ inline int shared_ptr<T>::use_count() const
+ {
+ return count_->count_;
+ }
+
+ template<class T>
+ inline void shared_ptr<T>::swap(shared_ptr<T>& other)
+ {
+ SharedCount* dummy = count_;
+ count_=other.count_;
+ other.count_ = dummy;
+ T* tdummy=rep_;
+ rep_ = other.rep_;
+ other.rep_ = tdummy;
+ }
+
+ template<class T>
+ inline void shared_ptr<T>::reset()
+ {
+ shared_ptr<T>().swap(*this);
+ }
+
+ template<class T>
+ template<class T1>
+ inline void shared_ptr<T>::reset(T1* pointer)
+ {
+ shared_ptr<T>(pointer).swap(*this);
+ }
+
+ template<class T>
+ template<class T1, class Deleter>
+ inline void shared_ptr<T>::reset(T1* pointer, Deleter deleter)
+ {
+ shared_ptr<T>(pointer, deleter).swap(*this);
+ }
+
+ /** @} */
+#endif // #ifdef SHARED_PTR_NAMESPACE
+
+
+ // C++0x and Boost have a make_shared implementation, TR1 does not.
+ // Unfortunately, TR1 gets picked over Boost if present.
+ // Moreover, boost::make_shared() only exists for (remotely) recent versions of Boost.
+#if HAVE_MAKE_SHARED
+#ifdef SHARED_PTR_NAMESPACE
+ using SHARED_PTR_NAMESPACE :: make_shared;
+#endif
+#else
+
+ template<typename T>
+ shared_ptr<T> make_shared()
+ {
+ return shared_ptr<T>(new T());
+ }
+
+ template<typename T, typename Arg1>
+ shared_ptr<T> make_shared(const Arg1& arg1)
+ {
+ return shared_ptr<T>(new T(arg1));
+ }
+
+ template<typename T, typename Arg1, typename Arg2>
+ shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2)
+ {
+ return shared_ptr<T>(new T(arg1,arg2));
+ }
+
+ template<typename T, typename Arg1, typename Arg2, typename Arg3>
+ shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3)
+ {
+ return shared_ptr<T>(new T(arg1,arg2,arg3));
+ }
+
+ template<typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+ shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4)
+ {
+ return shared_ptr<T>(new T(arg1,arg2,arg3,arg4));
+ }
+
+ template<typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4,
+ typename Arg5>
+ shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4,
+ const Arg5& arg5)
+ {
+ return shared_ptr<T>(new T(arg1,arg2,arg3,arg4,arg5));
+ }
+
+ template<typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4,
+ typename Arg5, typename Arg6>
+ shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4,
+ const Arg5& arg5, const Arg6& arg6)
+ {
+ return shared_ptr<T>(new T(arg1,arg2,arg3,arg4,arg5,arg6));
+ }
+
+ template<typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4,
+ typename Arg5, typename Arg6, typename Arg7>
+ shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4,
+ const Arg5& arg5, const Arg6& arg6, const Arg7& arg7)
+ {
+ return shared_ptr<T>(new T(arg1,arg2,arg3,arg4,arg5,arg6,arg7));
+ }
+
+ template<typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4,
+ typename Arg5, typename Arg6, typename Arg7, typename Arg8>
+ shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4,
+ const Arg5& arg5, const Arg6& arg6, const Arg7& arg7, const Arg8& arg8)
+ {
+ return shared_ptr<T>(new T(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8));
+ }
+
+ template<typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4,
+ typename Arg5, typename Arg6, typename Arg7, typename Arg8, typename Arg9>
+ shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4,
+ const Arg5& arg5, const Arg6& arg6, const Arg7& arg7, const Arg8& arg8,
+ const Arg9& arg9)
+ {
+ return shared_ptr<T>(new T(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9));
+ }
+
+#endif // custom make_shared
+
+ /**
+ @brief implements the Deleter concept of shared_ptr without deleting anything
+ @relates shared_ptr
+
+ If you allocate an object on the stack, but want to pass it to a class or function as a shared_ptr,
+ you can use this deleter to avoid accidental deletion of the stack-allocated object.
+
+ For convenience we provide two free functions to create a shared_ptr from a stack-allocated object
+ (\see stackobject_to_shared_ptr):
+
+ 1) Convert a stack-allocated object to a shared_ptr:
+ @code
+ int i = 10;
+ shared_ptr<int> pi = stackobject_to_shared_ptr(i);
+ @endcode
+ 2) Convert a stack-allocated object to a shared_ptr of a base class
+ @code
+ class A {};
+ class B : public A {};
+
+ ...
+
+ B b;
+ shared_ptr<A> pa = stackobject_to_shared_ptr<A>(b);
+ @endcode
+
+ @tparam T type of the stack-allocated object
+ */
+ template<class T>
+ struct null_deleter
+ {
+ void operator() (T*) const {}
+ };
+
+ /**
+ @brief Convert a stack-allocated object to a shared_ptr:
+ @relates shared_ptr
+ @code
+ int i = 10;
+ shared_ptr<int> pi = stackobject_to_shared_ptr(i);
+ @endcode
+ */
+ template<typename T>
+ inline shared_ptr<T> stackobject_to_shared_ptr(T & t)
+ {
+ return shared_ptr<T>(&t, null_deleter<T>());
+ }
+
+ /**
+ @brief Convert a stack object to a shared_ptr of a base class
+ @relates shared_ptr
+ @code
+ class A {};
+ class B : public A {};
+
+ ...
+
+ B b;
+ shared_ptr<A> pa = stackobject_to_shared_ptr<A>(b);
+ @endcode
+ */
+ template<typename T, typename T2>
+ inline shared_ptr<T2> stackobject_to_shared_ptr(T & t)
+ {
+ return shared_ptr<T2>(dynamic_cast<T2*>(&t), null_deleter<T2>());
+ }
+
+}
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_SINGLETON_HH
+#define DUNE_SINGLETON_HH
+
+#include <memory>
+
+/**
+ * @file
+ * @brief Useful wrapper for creating singletons.
+ *
+ * Inspired by the article
+ * <a href="http://www.codeguru.com/cpp/cpp/cpp_mfc/singletons/article.php/c755/">CodeGuru: A Leak-Free Singleton class</a>
+ */
+namespace Dune
+{
+ /**
+ * @brief An adapter to turn a class into a singleton.
+ *
+ * The class represented by the template parameter T must
+ * have a parameterless constructor.
+ *
+ * Class T can be publicly derived from Singleton<T>:
+ *
+ * \code
+ * #include<dune/common/singleton.hh>
+ * class Foo : public Dune::Singleton<Foo>
+ * {
+ * public:
+ * Foo()
+ * {
+ * bytes = new char[1000];
+ * }
+ *
+ * ~Foo()
+ * {
+ * delete[] bytes;
+ * }
+ * private:
+ * char* bytes;
+ * };
+ * \endcode
+ *
+ * Or one can construct a Singleton of an existing class. Say Foo1 is a class
+ * with parameterless constructor then
+ * \code
+ * typedef Dune::Singleton<Foo1> FooSingleton;
+ * Foo1 instance& = FooSingleton::instance();
+ * \endcode
+ * Creates a singleton of that class and accesses its instance.
+ */
+ template<class T>
+ class Singleton
+ {
+ /** @brief Smartpointer to the instance. */
+ static std::auto_ptr<T> instance_;
+ protected:
+ /* @brief Private constructor. */
+ Singleton(){}
+ /** @brief Private copy constructor. */
+ Singleton(const Singleton&){}
+ /** @brief Private assignment operator. */
+ Singleton& operator=(const Singleton&){}
+
+ public:
+ /**
+ * @brief Get the instance of the singleton.
+ * @return The instance of the singleton.
+ */
+ static T& instance()
+ {
+ if(instance_.get() == 0)
+ instance_ = std::auto_ptr<T>(new T());
+ return *instance_;
+ }
+ };
+
+ template<class T>
+ typename std::auto_ptr<T> Singleton<T>::instance_;
+
+} // namespace Dune
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+#ifndef DUNE_SLLIST_HH
+#define DUNE_SLLIST_HH
+
+#include <memory>
+#include <cassert>
+#include "iteratorfacades.hh"
+#include <ostream>
+
+namespace Dune
+{
+ /**
+ * @addtogroup Common
+ *
+ * @{
+ */
+ /**
+ * @file
+ * \brief Implements a singly linked list together with
+ * the necessary iterators.
+ * @author Markus Blatt
+ */
+ template<typename T, class A>
+ class SLListIterator;
+
+ template<typename T, class A>
+ class SLListConstIterator;
+
+ template<typename T, class A>
+ class SLListModifyIterator;
+
+ /**
+ * @brief A single linked list.
+ *
+ * The list is capable of insertions at the front and at
+ * the end and of removing elements at the front. Those
+ * operations require constant time.
+ */
+ template<typename T, class A=std::allocator<T> >
+ class SLList
+ {
+ struct Element;
+ friend class SLListIterator<T,A>;
+ friend class SLListConstIterator<T,A>;
+
+ public:
+
+ /**
+ * @brief The size type.
+ */
+ typedef typename A::size_type size_type;
+
+ /**
+ * @brief The type we store.
+ */
+ typedef T MemberType;
+
+ /**
+ * @brief The allocator to use.
+ */
+ typedef typename A::template rebind<Element>::other Allocator;
+
+ /**
+ * @brief The mutable iterator of the list.
+ */
+ typedef SLListIterator<T,A> iterator;
+
+ /**
+ * @brief The constant iterator of the list.
+ */
+ typedef SLListConstIterator<T,A> const_iterator;
+
+ /**
+ * @brief Constructor.
+ */
+ SLList();
+
+ /**
+ * @brief Copy constructor with type conversion.
+ */
+ template<typename T1, typename A1>
+ SLList(const SLList<T1,A1>& other);
+
+ /**
+ * @brief Copy constructor.
+ */
+ SLList(const SLList<T,A>& other);
+
+ /**
+ * @brief Destructor.
+ *
+ * Deallocates all elements in the list.
+ */
+ ~SLList();
+
+ /**
+ * @brief The type of the iterator capable of deletion
+ * and insertion.
+ */
+ typedef SLListModifyIterator<T,A> ModifyIterator;
+
+ /**
+ * @brief Assignment operator.
+ */
+ SLList<T,A>& operator=(const SLList<T,A>& other);
+
+
+ /**
+ * @brief Add a new entry to the end of the list.
+ * @param item The item to add.
+ */
+ inline void push_back(const MemberType& item);
+
+ /**
+ * @brief Add a new entry to the beginning of the list.
+ * @param item The item to add.
+ */
+ inline void push_front(const MemberType& item);
+
+ /**
+ * @brief Remove the first item in the list.
+ */
+ inline void pop_front();
+
+ /** @brief Remove all elements from the list. */
+ inline void clear();
+
+ /**
+ * @brief Get an iterator pointing to the first
+ * element in the list.
+ *
+ * @return An iterator pointing to the first
+ * element or the end if the list is empty.
+ */
+ inline iterator begin();
+
+ /**
+ * @brief Get an iterator pointing to the first
+ * element in the list.
+ *
+ * @return An iterator pointing to the first
+ * element or the end if the list is empty.
+ */
+ inline const_iterator begin() const;
+
+ /**
+ * @brief Get an iterator capable of deleting and
+ * inserting elements.
+ *
+ * @return Modifying iterator positioned at the beginning
+ * of the list.
+ */
+ inline ModifyIterator beginModify();
+
+ /**
+ * @brief Get an iterator capable of deleting and
+ * inserting elements.
+ *
+ * @return Modifying iterator positioned after the end
+ * of the list.
+ */
+ inline ModifyIterator endModify();
+
+ /**
+ * @brief Get an iterator pointing to the
+ * end of the list.
+ *
+ * @return An iterator pointing to the end.
+ */
+ inline iterator end();
+
+ /**
+ * @brief Get an iterator pointing to the
+ * end of the list.
+ *
+ * @return An iterator pointing to the end.
+ */
+ inline const_iterator end() const;
+
+ /**
+ * @brief Check whether the list is empty.
+ *
+ * @return True if the list is empty;
+ */
+ inline bool empty() const;
+
+ /**
+ * @brief Get the number of elements the list
+ * contains.
+ */
+ inline int size() const;
+
+ bool operator==(const SLList& sl) const;
+
+
+ bool operator!=(const SLList& sl) const;
+
+ private:
+ /** \todo Please doc me! */
+ struct Element
+ {
+ /**
+ * @brief The next element in the list.
+ */
+ Element* next_;
+ /**
+ * @brief The element we hold.
+ */
+ MemberType item_;
+
+ Element(const MemberType& item, Element* next_=0);
+
+ Element();
+
+ ~Element();
+ };
+
+ /**
+ * @brief Delete the next element in the list.
+ * @param current Element whose next element should be deleted.
+ */
+ void deleteNext(Element* current);
+
+ /**
+ * @brief Copy the elements from another list.
+ * @param other The other list.
+ */
+ void copyElements(const SLList<T,A>& other);
+
+ /**
+ * @brief Delete the next element in the list.
+ *
+ * If the template parameter watchForTail is true, it is checked whether
+ * the deleted element is the tail and therefore the tail must be updated.
+ * @param current Element whose next element should be deleted.
+ */
+ template<bool watchForTail>
+ void deleteNext(Element* current);
+ /**
+ * @brief Insert an element after another one in the list.
+ * @param current The element after which we insert.
+ * @param item The item to insert.
+ */
+ void insertAfter(Element* current, const T& item);
+
+ /** @brief Pseudo element before the first entry. */
+ Element beforeHead_;
+
+ /**
+ * @brief Pointer to he last element in the list.
+ *
+ * If list is empty this will point to beforeHead_
+ */
+ Element* tail_;
+
+ /** @brief The allocator we use. */
+ Allocator allocator_;
+
+ /** brief The number of elements the list holds. */
+ int size_;
+ };
+
+ /**
+ * @brief A mutable iterator for the SLList.
+ */
+ template<typename T, class A>
+ class SLListIterator : public Dune::ForwardIteratorFacade<SLListIterator<T,A>, T, T&, std::size_t>
+ {
+ friend class SLListConstIterator<T,A>;
+ friend class SLListModifyIterator<T,A>;
+ friend class SLList<T,A>;
+
+ public:
+ inline SLListIterator(typename SLList<T,A>::Element* item,
+ SLList<T,A>* sllist)
+ : current_(item), list_(sllist)
+ {}
+
+ inline SLListIterator()
+ : current_(0), list_(0)
+ {}
+
+ inline SLListIterator(const SLListModifyIterator<T,A>& other)
+ : current_(other.iterator_.current_), list_(other.iterator_.list_)
+ {}
+
+ /**
+ * @brief Dereferencing function for the iterator facade.
+ * @return A reference to the element at the current position.
+ */
+ inline T& dereference() const
+ {
+ return current_->item_;
+ }
+
+ /**
+ * @brief Equality test for the iterator facade.
+ * @param other The other iterator to check.
+ * @return true If the other iterator is at the same position.
+ */
+ inline bool equals(const SLListConstIterator<T,A>& other) const
+ {
+ return current_==other.current_;
+ }
+
+ /**
+ * @brief Equality test for the iterator facade.
+ * @param other The other iterator to check.
+ * @return true If the other iterator is at the same position.
+ */
+ inline bool equals(const SLListIterator<T,A>& other) const
+ {
+ return current_==other.current_;
+ }
+
+ /**
+ * @brief Equality test for the iterator facade.
+ * @param other The other iterator to check.
+ * @return true If the other iterator is at the same position.
+ */
+ inline bool equals(const SLListModifyIterator<T,A>& other) const
+ {
+ return current_==other.iterator_.current_;
+ }
+
+ /**
+ * @brief Increment function for the iterator facade.
+ */
+ inline void increment()
+ {
+ current_ = current_->next_;
+ }
+
+ /**
+ * @brief Insert an element in the underlying list after
+ * the current position.
+ * @param v The value to insert.
+ */
+ inline void insertAfter(const T& v) const
+ {
+ assert(list_ );
+ list_->insertAfter(current_, v);
+ }
+
+ /**
+ * @brief Delete the entry after the current position.
+ *
+ * @warning This will invalidate all iterators positioned at the delete position! Use with care!
+ */
+ inline void deleteNext() const
+ {
+ assert(list_);
+ list_->deleteNext(current_);
+ }
+
+ private:
+ /** @brief The current element. */
+ typename SLList<T,A>::Element* current_;
+ /** @brief The list we iterate over. */
+ SLList<T,A>* list_;
+ };
+
+ /**
+ * @brief A constant iterator for the SLList.
+ */
+ template<class T, class A>
+ class SLListConstIterator : public Dune::ForwardIteratorFacade<SLListConstIterator<T,A>, const T, const T&, std::size_t>
+ {
+ friend class SLListIterator<T,A>;
+ friend class SLList<T,A>;
+
+ public:
+ inline SLListConstIterator()
+ : current_(0)
+ {}
+
+ inline SLListConstIterator(typename SLList<T,A>::Element* item)
+ : current_(item)
+ {}
+
+ inline SLListConstIterator(const SLListIterator<T,A>& other)
+ : current_(other.current_)
+ {}
+
+ inline SLListConstIterator(const SLListConstIterator<T,A>& other)
+ : current_(other.current_)
+ {}
+
+ inline SLListConstIterator(const SLListModifyIterator<T,A>& other)
+ : current_(other.iterator_.current_)
+ {}
+
+ /**
+ * @brief Dereferencing function for the facade.
+ * @return A reference to the element at the current position.
+ */
+ inline const T& dereference() const
+ {
+ return current_->item_;
+ }
+
+ /**
+ * @brief Equality test for the iterator facade.
+ * @param other The other iterator to check.
+ * @return true If the other iterator is at the same position.
+ */
+ inline bool equals(const SLListConstIterator<T,A>& other) const
+ {
+ return current_==other.current_;
+ }
+
+ /**
+ * @brief Increment function for the iterator facade.
+ */
+ inline void increment()
+ {
+ current_ = current_->next_;
+ }
+
+ private:
+ /** @brief The current element. */
+ typename SLList<T,A>::Element* current_;
+ };
+
+ /**
+ * @brief A mutable iterator for the SLList.
+ */
+ template<typename T, class A>
+ class SLListModifyIterator : public Dune::ForwardIteratorFacade<SLListModifyIterator<T,A>, T, T&, std::size_t>
+ {
+ friend class SLListConstIterator<T,A>;
+ friend class SLListIterator<T,A>;
+ public:
+ inline SLListModifyIterator(SLListIterator<T,A> beforeIterator,
+ SLListIterator<T,A> _iterator)
+ : beforeIterator_(beforeIterator), iterator_(_iterator)
+ {}
+
+ inline SLListModifyIterator(const SLListModifyIterator<T,A>& other)
+ : beforeIterator_(other.beforeIterator_), iterator_(other.iterator_)
+ {}
+
+ inline SLListModifyIterator()
+ : beforeIterator_(), iterator_()
+ {}
+
+ /**
+ * @brief Dereferencing function for the iterator facade.
+ * @return A reference to the element at the current position.
+ */
+ inline T& dereference() const
+ {
+ return *iterator_;
+ }
+
+ /**
+ * @brief Test whether another iterator is equal.
+ * @return true if the other iterator is at the same position as
+ * this one.
+ */
+ inline bool equals(const SLListConstIterator<T,A>& other) const
+ {
+ return iterator_== other;
+ }
+
+
+ /**
+ * @brief Test whether another iterator is equal.
+ * @return true if the other iterator is at the same position as
+ * this one.
+ */
+ inline bool equals(const SLListIterator<T,A>& other) const
+ {
+ return iterator_== other;
+ }
+
+
+ /**
+ * @brief Test whether another iterator is equal.
+ * @return true if the other iterator is at the same position as
+ * this one.
+ */
+ inline bool equals(const SLListModifyIterator<T,A>& other) const
+ {
+ return iterator_== other.iterator_;
+ }
+
+ /**
+ * @brief Increment function for the iterator facade.
+ */
+ inline void increment()
+ {
+ ++iterator_;
+ ++beforeIterator_;
+ }
+
+ /**
+ * @brief Insert an element at the current position.
+ *
+ * Starting from the element at the current position all
+ * elements will be shifted by one position to the back.
+ * The iterator will point to the same element as before
+ * after the insertion, i.e the number of increments to
+ * reach the same position from a begin iterator increases
+ * by one.
+ * This means the inserted element is the one before the one
+ * the iterator points to.
+ * @param v The value to insert.
+ */
+ inline void insert(const T& v)
+ {
+ beforeIterator_.insertAfter(v);
+ ++beforeIterator_;
+ }
+
+ /**
+ * @brief Delete the entry at the current position.
+ *
+ * The iterator will be positioned at the next postion after the
+ * deletion
+ * @warning This will invalidate all iterators positioned at the delete position! Use with care!
+ */
+ inline void remove()
+ {
+ ++iterator_;
+ beforeIterator_.deleteNext();
+ }
+
+ private:
+ /** @brief Iterator positioned at the position before the current. */
+ SLListIterator<T,A> beforeIterator_;
+ /** @brief Iterator positioned at the current position. */
+ SLListIterator<T,A> iterator_;
+ };
+} // namespace Dune
+
+namespace std
+{
+
+ template<typename T, typename A>
+ ostream& operator<<(ostream& os, const Dune::SLList<T,A> sllist)
+ {
+ typedef typename Dune::SLList<T,A>::const_iterator Iterator;
+ Iterator end = sllist.end();
+ Iterator current= sllist.begin();
+
+ os << "{ ";
+
+ if(current!=end) {
+ os<<*current<<" ("<<static_cast<const void*>(&(*current))<<")";
+ ++current;
+
+ for(; current != end; ++current)
+ os<<", "<<*current<<" ("<<static_cast<const void*>(&(*current))<<")";
+ }
+ os<<"} ";
+ return os;
+ }
+} //namespace std
+
+namespace Dune
+{
+
+ template<typename T, class A>
+ SLList<T,A>::Element::Element(const MemberType& item, Element* next)
+ : next_(next), item_(item)
+ {}
+
+ template<typename T, class A>
+ SLList<T,A>::Element::Element()
+ : next_(0), item_()
+ {}
+
+ template<typename T, class A>
+ SLList<T,A>::Element::~Element()
+ {
+ next_=0;
+ }
+
+ template<typename T, class A>
+ SLList<T,A>::SLList()
+ : beforeHead_(), tail_(&beforeHead_), allocator_(), size_(0)
+ {
+ beforeHead_.next_=0;
+ assert(&beforeHead_==tail_);
+ assert(tail_->next_==0);
+ }
+
+ template<typename T, class A>
+ SLList<T,A>::SLList(const SLList<T,A>& other)
+ : beforeHead_(), tail_(&beforeHead_), allocator_(), size_(0)
+ {
+ copyElements(other);
+ }
+
+ template<typename T, class A>
+ template<typename T1, class A1>
+ SLList<T,A>::SLList(const SLList<T1,A1>& other)
+ : beforeHead_(), tail_(&beforeHead_), allocator_(), size_(0)
+ {
+ copyElements(other);
+ }
+
+ template<typename T, typename A>
+ void SLList<T,A>::copyElements(const SLList<T,A>& other)
+ {
+ assert(tail_==&beforeHead_);
+ assert(size_==0);
+ typedef typename SLList<T,A>::const_iterator Iterator;
+ Iterator iend = other.end();
+ for(Iterator element=other.begin(); element != iend; ++element)
+ push_back(*element);
+
+ assert(other.size()==size());
+ }
+
+ template<typename T, class A>
+ SLList<T,A>::~SLList()
+ {
+ clear();
+ }
+
+ template<typename T, class A>
+ bool SLList<T,A>::operator==(const SLList& other) const
+ {
+ if(size()!=other.size())
+ return false;
+ for(const_iterator iter=begin(), oiter=other.begin();
+ iter != end(); ++iter, ++oiter)
+ if(*iter!=*oiter)
+ return false;
+ return true;
+ }
+
+ template<typename T, class A>
+ bool SLList<T,A>::operator!=(const SLList& other) const
+ {
+ if(size()==other.size()) {
+ for(const_iterator iter=begin(), oiter=other.begin();
+ iter != end(); ++iter, ++oiter)
+ if(*iter!=*oiter)
+ return true;
+ return false;
+ }else
+ return true;
+ }
+ template<typename T, class A>
+ SLList<T,A>& SLList<T,A>::operator=(const SLList<T,A>& other)
+ {
+ clear();
+ copyElements(other);
+ return *this;
+ }
+
+ template<typename T, class A>
+ inline void SLList<T,A>::push_back(const MemberType& item)
+ {
+ assert(size_>0 || tail_==&beforeHead_);
+ tail_->next_ = allocator_.allocate(1, 0);
+ assert(size_>0 || tail_==&beforeHead_);
+ tail_ = tail_->next_;
+ ::new (static_cast<void*>(&(tail_->item_)))T(item);
+ tail_->next_=0;
+ assert(tail_->next_==0);
+ ++size_;
+ }
+
+ template<typename T, class A>
+ inline void SLList<T,A>::insertAfter(Element* current, const T& item)
+ {
+ assert(current);
+
+#ifndef NDEBUG
+ bool changeTail = (current == tail_);
+#endif
+
+ // Save old next element
+ Element* tmp = current->next_;
+
+ assert(!changeTail || !tmp);
+
+ // Allocate space
+ current->next_ = allocator_.allocate(1, 0);
+
+ // Use copy constructor to initialize memory
+ allocator_.construct(current->next_, Element(item,tmp));
+
+ //::new(static_cast<void*>(&(current->next_->item_))) T(item);
+
+ if(!current->next_->next_) {
+ // Update tail
+ assert(changeTail);
+ tail_ = current->next_;
+ }
+ ++size_;
+ assert(!tail_->next_);
+ }
+
+ template<typename T, class A>
+ inline void SLList<T,A>::push_front(const MemberType& item)
+ {
+ if(tail_ == &beforeHead_) {
+ // list was empty
+ beforeHead_.next_ = tail_ = allocator_.allocate(1, 0);
+ ::new(static_cast<void*>(&beforeHead_.next_->item_))T(item);
+ beforeHead_.next_->next_=0;
+ }else{
+ Element* added = allocator_.allocate(1, 0);
+ ::new(static_cast<void*>(&added->item_))T(item);
+ added->next_=beforeHead_.next_;
+ beforeHead_.next_=added;
+ }
+ assert(tail_->next_==0);
+ ++size_;
+ }
+
+
+ template<typename T, class A>
+ inline void SLList<T,A>::deleteNext(Element* current)
+ {
+ this->template deleteNext<true>(current);
+ }
+
+ template<typename T, class A>
+ template<bool watchForTail>
+ inline void SLList<T,A>::deleteNext(Element* current)
+ {
+ assert(current->next_);
+ Element* next = current->next_;
+
+ if(watchForTail)
+ if(next == tail_) {
+ // deleting last element changes tail!
+ tail_ = current;
+ }
+
+ current->next_ = next->next_;
+ allocator_.destroy(next);
+ allocator_.deallocate(next, 1);
+ --size_;
+ assert(!watchForTail || &beforeHead_ != tail_ || size_==0);
+ }
+
+ template<typename T, class A>
+ inline void SLList<T,A>::pop_front()
+ {
+ deleteNext(&beforeHead_);
+ }
+
+ template<typename T, class A>
+ inline void SLList<T,A>::clear()
+ {
+ while(beforeHead_.next_ ) {
+ this->template deleteNext<false>(&beforeHead_);
+ }
+
+ assert(size_==0);
+ // update the tail!
+ tail_ = &beforeHead_;
+ }
+
+ template<typename T, class A>
+ inline bool SLList<T,A>::empty() const
+ {
+ return (&beforeHead_ == tail_);
+ }
+
+ template<typename T, class A>
+ inline int SLList<T,A>::size() const
+ {
+ return size_;
+ }
+
+ template<typename T, class A>
+ inline SLListIterator<T,A> SLList<T,A>::begin()
+ {
+ return iterator(beforeHead_.next_, this);
+ }
+
+ template<typename T, class A>
+ inline SLListConstIterator<T,A> SLList<T,A>::begin() const
+ {
+ return const_iterator(beforeHead_.next_);
+ }
+
+ template<typename T, class A>
+ inline SLListIterator<T,A> SLList<T,A>::end()
+ {
+ return iterator();
+ }
+
+ template<typename T, class A>
+ inline SLListModifyIterator<T,A> SLList<T,A>::endModify()
+ {
+ return SLListModifyIterator<T,A>(iterator(tail_, this),iterator());
+ }
+
+
+ template<typename T, class A>
+ inline SLListModifyIterator<T,A> SLList<T,A>::beginModify()
+ {
+ return SLListModifyIterator<T,A>(iterator(&beforeHead_, this),
+ iterator(beforeHead_.next_, this));
+ }
+
+ template<typename T, class A>
+ inline SLListConstIterator<T,A> SLList<T,A>::end() const
+ {
+ return const_iterator();
+ }
+
+ /** }@ */
+}
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_STATIC_ASSERT_HH
+#define DUNE_STATIC_ASSERT_HH
+
+/** \file
+ * \brief Fallback implementation of the C++0x static_assert feature
+ */
+
+/**
+ * @addtogroup Common
+ *
+ * @{
+ */
+
+#if not HAVE_STATIC_ASSERT
+// Taken from BOOST
+//
+// Helper macro CPPMAGIC_JOIN:
+// The following piece of macro magic joins the two
+// arguments together, even when one of the arguments is
+// itself a macro (see 16.3.1 in C++ standard). The key
+// is that macro expansion of macro arguments does not
+// occur in CPPMAGIC_DO_JOIN2 but does in CPPMAGIC_DO_JOIN.
+//
+#define CPPMAGIC_JOIN( X, Y ) CPPMAGIC_DO_JOIN( X, Y )
+#define CPPMAGIC_DO_JOIN( X, Y ) CPPMAGIC_DO_JOIN2(X,Y)
+#define CPPMAGIC_DO_JOIN2( X, Y ) X ## Y
+
+template <bool x> struct static_assert_failure;
+
+template <> struct static_assert_failure<true> { };
+
+template<int x> struct static_assert_test {};
+#endif
+
+/**
+ \brief Helper template so that compilation fails if condition is not true.
+
+ \code
+ #include <dune/common/static_assert.hh>
+ dune_static_assert(CONDITION, ERRORMSG);
+ \endcode
+
+ If CONDITION is not true, dune_static_assert fails.
+
+ If the C++0x language feature static_assert is available, dune_static_assert
+ forwards everything to static_assert. Otherwise dune_static_assert implements a
+ test that triggers a compile time error if the condition is false.
+
+ Example:
+
+ \code
+ dune_static_assert(1<=2, "error");
+ dune_static_assert((is_same<int,int>::value), "error msg");
+ dune_static_assert((is_same<bool,int>::value), "error msg"); // false, will trigger a compile time error
+ \endcode
+
+ \note
+ \code
+ dune_static_assert(false, "error");
+ \endcode
+ will usually not do what was intended, see Dune::AlwaysFalse for a way to
+ achieve the desired result.
+
+ Be aware that...
+ <ol>
+ <li>dune_static_assert is not in the namespace Dune</li>
+ <li>you must use extra parentheses if your condition contains ','.
+ This is because dune_static_assert is a preprocessor macro</li>
+ </ol>
+
+ */
+
+#if HAVE_STATIC_ASSERT
+#define dune_static_assert(COND,MSG) \
+ static_assert(COND,MSG)
+#else
+#define dune_static_assert(COND,MSG) \
+ typedef static_assert_test< \
+ sizeof(static_assert_failure< (bool)( COND )>)\
+ > CPPMAGIC_JOIN (dune_static_assert_typedef_, __LINE__)
+#endif
+
+namespace Dune {
+ /**
+ \brief template which always yields a false value
+ \tparam T Some type. It sould be a type expression involving template
+ parameters of the class or function using AlwaysFalse.
+
+ Suppose you have a template class. You want to document the required
+ members of this class in the non-specialized template, but you know that
+ actually instantiating the non-specialized template is an error. You
+ can try something like this:
+ \code
+ template<typename T>
+ struct Traits {
+ dune_static_assert(false,
+ "Instanciating this non-specialized template is an "
+ "error. You should use one of the specializations "
+ "instead.");
+ //! The type used to frobnicate T
+ typedef void FrobnicateType;
+ };
+ \endcode
+ This will trigger dune_static_assert() as soon as the compiler reads the
+ definition for the Traits template, since it knows that "false" can
+ never become true, no matter what the template parameters of Traits are.
+ As a workaround you can use AlwaysFalse: replace <tt>false</tt> by
+ <tt>AlwaysFalse<T>::value</tt>, like this:
+ \code
+ template<typename T>
+ struct Traits {
+ dune_static_assert(AlwaysFalse<T>::value,
+ "Instanciating this non-specialized template is an "
+ "error. You should use one of the specializations "
+ "instead.");
+ //! The type used to frobnicate T
+ typedef void FrobnicateType;
+ };
+ \endcode
+ Since there might be an specialization of AlwaysFalse for template
+ parameter T, the compiler cannot trigger dune_static_assert() until the
+ type of T is known, that is, until Traits<T> is instantiated.
+ */
+ template<typename T>
+ struct AlwaysFalse {
+ //! always a false value
+ static const bool value = false;
+ };
+
+ /**
+ \brief template which always yields a true value
+ \tparam T Some type. It sould be a type expression involving template
+ parameters of the class or function using AlwaysTrue.
+
+ \note This class exists mostly for consistency with AlwaysFalse.
+ */
+ template<typename T>
+ struct AlwaysTrue {
+ //! always a true value
+ static const bool value = true;
+ };
+} // namespace Dune
+
+/* @} */
+
+#endif
--- /dev/null
+install(FILES
+ constexpr.hh
+DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/common/std)
--- /dev/null
+stdincludedir = $(includedir)/dune/common/std
+stdinclude_HEADERS = \
+ constexpr.hh
+
+EXTRA_DIST = CMakeLists.txt
+
+include $(top_srcdir)/am/global-rules
--- /dev/null
+#ifndef DUNE_COMMON_STD_CONSTEXPR_HH
+#define DUNE_COMMON_STD_CONSTEXPR_HH
+
+#if HAVE_CONSTEXPR
+#define DUNE_CONSTEXPR constexpr
+#else // #if HAVE_CONSTEXPR
+#define DUNE_CONSTEXPR
+#endif // #else // #if HAVE_CONSTEXPR
+
+#endif // #ifndef DUNE_COMMON_STD_CONSTEXPR_HH
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "stdstreams.hh"
+
+namespace Dune {
+
+ /*
+
+ The standard debug streams declared in stdstreams.hh exist in this
+ file so that they can be compiled into libdune
+
+ */
+
+ /* stream for very verbose output: information on the lowest
+ level. This is expected to report insane amounts of
+ information. Use of the activation-flag to only generate output
+ near the problem is recommended */
+ DVVerbType dvverb(std::cout);
+
+ /* stream for verbose output: information that helps to trace in
+ more detail what the modules do */
+ DVerbType dverb(std::cout);
+
+ /* stream for informative output: summary infos on what a module
+ does, runtimes, etc. */
+ DInfoType dinfo(std::cout);
+
+ /* stream for warnings: messages which may indicate problems */
+ DWarnType dwarn(std::cerr);
+
+ /* stream for strong warnings: when a failure */
+ DGraveType dgrave(std::cerr);
+
+ /* stream for error messages: only packages integrating Dune
+ completely will redirect it. The output of derr is independent of
+ the debug-level, only the activation-flag is checked */
+ DErrType derr(std::cerr);
+
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+
+/**
+ \file
+ \brief Standard Dune debug streams
+
+ The standard debug streams are compiled into libdune to exist
+ globally. This file declares the stream types and the global debug
+ level.
+ */
+
+#ifndef DUNE_COMMON_STDSTREAMS_HH
+#define DUNE_COMMON_STDSTREAMS_HH
+
+#include "debugstream.hh"
+
+namespace Dune {
+
+ /**
+ \addtogroup DebugOut
+ @{
+
+ standard debug streams with level below MINIMAL_DEBUG_LEVEL will
+ collapse to doing nothing if output is requested.
+
+ MINIMAL_DEBUG_LEVEL is set to DUNE_MINIMAL_DEBUG_LEVEL, wich is
+ defined in config.h and can be changed by the configure option
+ @code --with-minimal-debug-level=[grave|warn|info|verb|vverb] @endcode
+
+ For a Dune-Release this should be set to at least 4 so that only
+ important messages are active. Dune-developers may adapt this
+ setting to their debugging needs locally
+
+ Keep in mind that libdune has to be recompiled if this value is changed!
+
+
+
+ The singleton instances of the available debug streams can be found in
+ the \ref DebugOut "Standard Debug Streams" module
+
+ @}
+ */
+
+ /**
+ \defgroup StdStreams Standard Debug Streams
+ \ingroup DebugOut
+ @{
+
+ Dune defines several standard output streams for the library
+ routines.
+
+ Applications may control the standard streams via the attach/detach,
+ push/pop interface but should define an independent set of streams (see \ref DebugAppl )
+
+ */
+
+ /**
+ @brief The default minimum debug level.
+
+ If the level of a stream is bigger than this value
+ it will be activated.
+ */
+#ifndef DUNE_MINIMAL_DEBUG_LEVEL
+#define DUNE_MINIMAL_DEBUG_LEVEL 4
+#endif
+ static const DebugLevel MINIMAL_DEBUG_LEVEL = DUNE_MINIMAL_DEBUG_LEVEL;
+
+ /**
+ @brief The level of the very verbose debug stream.
+ @see dvverb
+ */
+ static const DebugLevel VERY_VERBOSE_DEBUG_LEVEL = 1;
+
+ /**
+ @brief Type of very verbose debug stream.
+ @see dvverb
+ */
+ typedef DebugStream<VERY_VERBOSE_DEBUG_LEVEL, MINIMAL_DEBUG_LEVEL> DVVerbType;
+
+ /**
+ \brief stream for very verbose output.
+
+ \code
+ #include <dune/common/stdstreams.hh>
+ \endcode
+
+ Information on the lowest
+ level. This is expected to report insane amounts of
+ information. Use of the activation-flag to only generate output
+ near the problem is recommended.
+ */
+ extern DVVerbType dvverb;
+
+ /**
+ @brief The level of the verbose debug stream.
+ @see dvverb
+ */
+ static const DebugLevel VERBOSE_DEBUG_LEVEL = 2;
+
+ /**
+ @brief Type of more verbose debug stream.
+ @see dverb
+ */
+ typedef DebugStream<VERBOSE_DEBUG_LEVEL, MINIMAL_DEBUG_LEVEL> DVerbType;
+
+ /**
+ @brief Singleton of verbose debug stream.
+
+ \code
+ #include <dune/common/stdstreams.hh>
+ \endcode
+ */
+ extern DVerbType dverb;
+
+ /**
+ @brief The level of the informative debug stream.
+ @see dinfo
+ */
+ static const DebugLevel INFO_DEBUG_LEVEL = 3;
+
+ /**
+ @brief Type of debug stream with info level.
+ @see dinfo
+ */
+ typedef DebugStream<INFO_DEBUG_LEVEL, MINIMAL_DEBUG_LEVEL> DInfoType;
+
+ /**
+ @brief Stream for informative output.
+
+ \code
+ #include <dune/common/stdstreams.hh>
+ \endcode
+
+ Summary infos on what a module
+ does, runtimes, etc.
+ */
+ extern DInfoType dinfo;
+
+ /**
+ @brief The level of the debug stream for warnings.
+ @see dwarn
+ */
+ static const DebugLevel WARN_DEBUG_LEVEL = 4;
+
+ /**
+ @brief Type of debug stream with warn level.
+ @see dwarn
+ */
+ typedef DebugStream<WARN_DEBUG_LEVEL, MINIMAL_DEBUG_LEVEL> DWarnType;
+
+ /**
+ @brief Stream for warnings indicating problems.
+
+ \code
+ #include <dune/common/stdstreams.hh>
+ \endcode
+ */
+ extern DWarnType dwarn;
+
+ /**
+ @brief The level of the debug stream for fatal errors.
+ @see dgrave
+ */
+ static const DebugLevel GRAVE_DEBUG_LEVEL = 5;
+
+ /** @brief Type of debug stream for fatal errors.*/
+ typedef DebugStream<GRAVE_DEBUG_LEVEL, MINIMAL_DEBUG_LEVEL> DGraveType;
+
+ /**
+ @brief Stream for warnings indicating fatal errors.
+
+ \code
+ #include <dune/common/stdstreams.hh>
+ \endcode
+ */
+ extern DGraveType dgrave;
+
+ /** @brief The type of the stream used for error messages. */
+ typedef DebugStream<1> DErrType;
+
+ /**
+ @brief Stream for error messages.
+
+ \code
+ #include <dune/common/stdstreams.hh>
+ \endcode
+
+ Only packages integrating Dune
+ completely will redirect it. The output of derr is independent of
+ the debug-level, only the activation-flag is checked.
+ */
+ extern DErrType derr;
+
+ /** }@ */
+}
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_COMMON_STRINGUTILITY_HH
+#define DUNE_COMMON_STRINGUTILITY_HH
+
+/** \file
+ \brief Miscellaneous helper stuff
+ */
+
+#include <cstddef>
+#include <cstring>
+#include <algorithm>
+
+namespace Dune {
+
+ /** @addtogroup Common
+
+ @{
+ */
+
+
+ /** \brief Check whether a character container has a given prefix
+ *
+ * The container must support the begin() and size() methods.
+ */
+ template<typename C>
+ bool hasPrefix(const C& c, const char* prefix) {
+ std::size_t len = std::strlen(prefix);
+ return c.size() >= len &&
+ std::equal(prefix, prefix+len, c.begin());
+ }
+
+ /** \brief Check whether a character container has a given suffix
+ *
+ * The container must support the the begin() and size() methods and the
+ * const_iterator member type.
+ *
+ * \note This is slow for containers which don't have random access iterators.
+ * In the case of containers with bidirectional iterators, this
+ * slowness is unnecessary.
+ */
+ template<typename C>
+ bool hasSuffix(const C& c, const char* suffix) {
+ std::size_t len = std::strlen(suffix);
+ if(c.size() < len) return false;
+ typename C::const_iterator it = c.begin();
+ std::advance(it, c.size() - len);
+ return std::equal(suffix, suffix+len, it);
+ }
+
+ /** @} */
+
+}
+
+#endif // DUNE_COMMON_STRINGUTILITY_HH
\ No newline at end of file
--- /dev/null
+# Stuff from the build system
+Makefile
+Makefile.in
+.deps
+.libs
+*.gcda
+*.gcno
+*.log
+*.trs
+gmon.out
+semantic.cache
+
+# The test binaries (in alphabetical order)
+arraylisttest
+arraytest
+bigunsignedinttest
+bitsetvectortest
+blockbitfieldtest
+check_fvector_size
+conversiontest
+diagonalmatrixtest
+dynmatrixtest
+dynvectortest
+eigenvaluestest
+enumsettest
+fassigntest
+fmatrixtest
+fvectortest
+gcdlcmtest
+iteratorfacadetest
+iteratorfacadetest2
+lrutest
+mpicollectivecommunication
+mpiguardtest
+mpihelpertest
+mpihelpertest2
+nullptr-test
+parametertreetest
+pathtest
+poolallocatortest
+shared_ptrtest
+singletontest
+shared_ptrtest_config
+shared_ptrtest_dune
+sllisttest
+static_assert_test
+streamtest
+testdebugallocator
+testdebugallocator_fail1
+testdebugallocator_fail2
+testdebugallocator_fail3
+testdebugallocator_fail4
+testdebugallocator_fail5
+testfassign_fail1
+testfassign_fail2
+testfassign_fail3
+testfassign_fail4
+testfassign_fail5
+testfassign_fail6
+testfassign1
+testfassign2
+testfassign3
+testfassign4
+testfloatcmp
+testfconstruct
+timing_xpr
+timing_old
+timing_flt
+tuplestest
+tuplestest_dune
+tuplestest_std
+tuplestest_tr1
+tupleutilitytest
+typetraitstest
+utilitytest
+
+tags
+TAGS
+
--- /dev/null
+# tests that should build and run successfully
+set(TESTS
+ arraylisttest
+ arraytest
+ bigunsignedinttest
+ bitsetvectortest
+ check_fvector_size
+ conversiontest
+ diagonalmatrixtest
+ dynmatrixtest
+ dynvectortest
+ eigenvaluestest
+ enumsettest
+ fassigntest
+ fmatrixtest
+ fvectortest
+ gcdlcmtest
+ iteratorfacadetest
+ iteratorfacadetest2
+ lrutest
+ mpicollectivecommunication
+ mpiguardtest
+ mpihelpertest
+ mpihelpertest2
+ nullptr_test
+ pathtest
+ parametertreetest
+ poolallocatortest
+ shared_ptrtest_config
+ shared_ptrtest_dune
+ singletontest
+ static_assert_test
+ streamtest
+ testfassign1
+ testfassign2
+ testfassign3
+ testfassign4
+ testfconstruct
+ testfloatcmp
+ tuplestest_config
+ tuplestest_dune
+ tuplestest_tr1
+ tupleutilitytest
+ utilitytest)
+
+#test that should build but fail to run successfully
+set(FAILTESTS
+ testdebugallocator_fail1
+ testdebugallocator_fail2
+ testdebugallocator_fail3
+ testdebugallocator_fail4
+ testdebugallocator_fail5
+ testfassign_fail1
+ testfassign_fail2
+ testfassign_fail3
+ testfassign_fail4
+ testfassign_fail5
+ testfassign_fail6)
+
+set(COMPILEFAILTESTS
+ check_fvector_size_fail1
+ check_fvector_size_fail2
+ genericiterator_compile_fail
+ nullptr-test-fail
+ static_assert_test_fail
+ testfconstruct_fail1
+ testfconstruct_fail2)
+
+set(TESTPROGS ${TESTS} ${FAILTESTS})
+
+# We do not want want to build the tests during make all,
+# but just build them on demand
+add_directory_test_target(_test_target)
+add_dependencies(${_test_target} ${TESTPROGS})
+
+# Add the executables needed for the tests
+add_executable("arraylisttest" arraylisttest.cc)
+add_executable("arraytest" arraytest.cc)
+
+add_executable("bigunsignedinttest" bigunsignedinttest.cc)
+target_link_libraries("bigunsignedinttest" "dunecommon")
+add_dune_boost_flags("bigunsignedinttest")
+
+add_executable("bitsetvectortest" bitsetvectortest.cc)
+add_executable("check_fvector_size" check_fvector_size.cc)
+add_executable("check_fvector_size_fail1" EXCLUDE_FROM_ALL check_fvector_size_fail.cc)
+set_target_properties(check_fvector_size_fail1 PROPERTIES COMPILE_FLAGS "-DDIM=1")
+add_executable("check_fvector_size_fail2" EXCLUDE_FROM_ALL check_fvector_size_fail.cc)
+set_target_properties(check_fvector_size_fail2 PROPERTIES COMPILE_FLAGS "-DDIM=3")
+add_executable("conversiontest" conversiontest.cc)
+
+add_executable("dynmatrixtest" dynmatrixtest.cc)
+target_link_libraries("dynmatrixtest" "dunecommon")
+
+add_executable("dynvectortest" dynvectortest.cc)
+
+add_executable("eigenvaluestest" eigenvaluestest.cc)
+target_link_libraries(eigenvaluestest dunecommon)
+if(LAPACK_FOUND)
+ target_link_libraries(eigenvaluestest ${LAPACK_LIBRARIES})
+endif(LAPACK_FOUND)
+
+add_executable("diagonalmatrixtest" diagonalmatrixtest.cc)
+target_link_libraries("diagonalmatrixtest" "dunecommon")
+
+add_executable("enumsettest" enumsettest.cc)
+
+add_executable("fassigntest" fassigntest.cc)
+target_link_libraries("fassigntest" "dunecommon")
+
+
+add_executable("testfloatcmp" testfloatcmp.cc)
+target_link_libraries("testfloatcmp" "dunecommon")
+
+# we provide an empty fortran file to force the linker
+# to link to the fortran libraries (needed for static linking)
+add_executable("fmatrixtest" fmatrixtest.cc dummy.f)
+target_link_libraries("fmatrixtest" "dunecommon")
+add_executable("fvectortest" fvectortest.cc)
+add_executable("gcdlcmtest" gcdlcmtest.cc)
+add_executable("genericiterator_compile_fail" EXCLUDE_FROM_ALL genericiterator_compile_fail.cc)
+add_executable("iteratorfacadetest2" iteratorfacadetest2.cc)
+add_executable("iteratorfacadetest" iteratorfacadetest.cc)
+add_executable("lrutest" lrutest.cc)
+target_link_libraries("lrutest" "dunecommon")
+add_executable("mpiguardtest" mpiguardtest.cc)
+target_link_libraries("mpiguardtest" "dunecommon")
+add_DUNE_MPI_flags(mpiguardtest)
+
+add_executable("mpicollectivecommunication" mpicollectivecommunication.cc)
+target_link_libraries(mpicollectivecommunication "dunecommon")
+add_DUNE_MPI_flags(mpicollectivecommunication)
+
+add_executable("mpihelpertest" mpihelpertest.cc)
+target_link_libraries(mpihelpertest "dunecommon")
+add_DUNE_MPI_flags(mpihelpertest)
+
+add_executable("mpihelpertest2" mpihelpertest.cc)
+target_link_libraries(mpihelpertest2 "dunecommon")
+add_DUNE_MPI_flags(mpihelpertest2)
+set_target_properties(mpihelpertest2 PROPERTIES COMPILE_FLAGS "-DMPIHELPER_PREINITIALIZE")
+
+add_executable("nullptr_test" nullptr-test.cc nullptr-test2.cc)
+target_link_libraries(nullptr_test "dunecommon")
+add_executable("nullptr_test_fail" EXCLUDE_FROM_ALL nullptr-test.cc)
+target_link_libraries(nullptr_test_fail "dunecommon")
+set_target_properties(nullptr_test_fail PROPERTIES COMPILE_FLAGS "-DFAIL")
+
+add_executable("parametertreetest" parametertreetest.cc)
+target_link_libraries("parametertreetest" "dunecommon")
+
+add_executable("pathtest" pathtest.cc)
+target_link_libraries("pathtest" "dunecommon")
+
+add_executable("poolallocatortest" poolallocatortest.cc)
+add_executable("shared_ptrtest_config" shared_ptrtest.cc)
+add_executable("shared_ptrtest_dune" shared_ptrtest.cc)
+set_target_properties(shared_ptrtest_dune PROPERTIES COMPILE_FLAGS "-DDISABLE_CONFIGURED_SHARED_PTR")
+add_executable("singletontest" singletontest.cc)
+add_executable("sllisttest" EXCLUDE_FROM_ALL sllisttest.cc)
+add_executable("static_assert_test" EXCLUDE_FROM_ALL static_assert_test.cc)
+add_executable("static_assert_test_fail" EXCLUDE_FROM_ALL static_assert_test_fail.cc)
+
+add_executable("streamtest" streamtest.cc)
+target_link_libraries("streamtest" "dunecommon")
+
+add_executable("testfassign1" testfassign.cc testfassign2.cc)
+set_target_properties(testfassign1 PROPERTIES COMPILE_FLAGS "-D_DUNE_TEST_N=3 -D_VALUES=\"1,2,3\"")
+target_link_libraries(testfassign1 "dunecommon")
+add_executable("testfassign2" testfassign.cc)
+set_target_properties(testfassign2 PROPERTIES COMPILE_FLAGS "-D_DUNE_TEST_N=3 -D_VALUES=\"1,zero\"")
+target_link_libraries(testfassign2 "dunecommon")
+add_executable("testfassign3" testfassign.cc)
+set_target_properties(testfassign3 PROPERTIES COMPILE_FLAGS "-D_DUNE_TEST_N=3 -D_VALUES=\"zero\"")
+target_link_libraries(testfassign3 "dunecommon")
+add_executable("testfassign4" testfassign.cc)
+set_target_properties(testfassign4 PROPERTIES COMPILE_FLAGS "-D_DUNE_TEST_N=2 -D_DUNE_TEST_M=3 -D_VALUES=\"1, zero, nextRow, 2, 3, 4\"")
+target_link_libraries(testfassign4 "dunecommon")
+
+add_executable("testdebugallocator" testdebugallocator.cc)
+target_link_libraries(testdebugallocator dunecommon)
+add_executable("testdebugallocator_fail1" testdebugallocator.cc)
+target_link_libraries(testdebugallocator_fail1 dunecommon)
+set_target_properties(testdebugallocator_fail1 PROPERTIES COMPILE_DEFINITIONS "FAILURE1")
+add_executable("testdebugallocator_fail2" testdebugallocator.cc)
+target_link_libraries(testdebugallocator_fail2 dunecommon)
+set_target_properties(testdebugallocator_fail2 PROPERTIES COMPILE_DEFINITIONS "FAILURE2")
+add_executable("testdebugallocator_fail3" testdebugallocator.cc)
+target_link_libraries(testdebugallocator_fail3 dunecommon)
+set_target_properties(testdebugallocator_fail3 PROPERTIES COMPILE_DEFINITIONS "FAILURE3")
+add_executable("testdebugallocator_fail4" testdebugallocator.cc)
+target_link_libraries(testdebugallocator_fail4 dunecommon)
+set_target_properties(testdebugallocator_fail4 PROPERTIES COMPILE_DEFINITIONS "FAILURE4;DEBUG_ALLOCATOR_KEEP=1")
+add_executable("testdebugallocator_fail5" testdebugallocator.cc)
+target_link_libraries(testdebugallocator_fail5 dunecommon)
+set_target_properties(testdebugallocator_fail5 PROPERTIES COMPILE_DEFINITIONS "FAILURE5")
+
+add_executable("testfassign_fail1" testfassign.cc)
+set_target_properties(testfassign_fail1 PROPERTIES COMPILE_FLAGS "-D_DUNE_TEST_N=3 -D_VALUES=\"1,2\"")
+target_link_libraries(testfassign_fail1 "dunecommon")
+add_executable("testfassign_fail2" testfassign.cc)
+set_target_properties(testfassign_fail2 PROPERTIES COMPILE_FLAGS "-D_DUNE_TEST_N=3 -D_VALUES=\"1,2,3,4\"")
+target_link_libraries(testfassign_fail2 "dunecommon")
+add_executable("testfassign_fail3" testfassign.cc)
+set_target_properties(testfassign_fail3 PROPERTIES COMPILE_FLAGS "-D_DUNE_TEST_N=2 -D_DUNE_TEST_M=2 -D_VALUES=\"1, nextRow, 2, 3\"")
+target_link_libraries(testfassign_fail3 "dunecommon")
+add_executable("testfassign_fail4" testfassign.cc)
+set_target_properties(testfassign_fail4 PROPERTIES COMPILE_FLAGS "-D_DUNE_TEST_N=2 -D_DUNE_TEST_M=2 -D_VALUES=\"1, 2, 3, nextRow, 2, 3\"")
+target_link_libraries(testfassign_fail4 "dunecommon")
+add_executable("testfassign_fail5" testfassign.cc)
+set_target_properties(testfassign_fail5 PROPERTIES COMPILE_FLAGS "-D_DUNE_TEST_N=2 -D_DUNE_TEST_M=2 -D_VALUES=\"1, 2\"")
+target_link_libraries(testfassign_fail5 "dunecommon")
+add_executable("testfassign_fail6" testfassign.cc)
+set_target_properties(testfassign_fail6 PROPERTIES COMPILE_FLAGS "-D_DUNE_TEST_N=2 -D_DUNE_TEST_M=2 -D_VALUES=\"1, 2, nextRow, 2, 3, nextRow, 4, 5\"")
+target_link_libraries(testfassign_fail6 "dunecommon")
+
+add_executable("testfconstruct" EXCLUDE_FROM_ALL testfconstruct.cc)
+set_target_properties(testfconstruct PROPERTIES COMPILE_FLAGS "-DFVSIZE=3")
+target_link_libraries(testfconstruct "dunecommon")
+add_executable("testfconstruct_fail1" EXCLUDE_FROM_ALL testfconstruct.cc)
+set_target_properties(testfconstruct_fail1 PROPERTIES COMPILE_FLAGS "-DFVSIZE=2")
+target_link_libraries(testfconstruct_fail1 "dunecommon")
+add_executable("testfconstruct_fail2" EXCLUDE_FROM_ALL testfconstruct.cc)
+set_target_properties(testfconstruct_fail2 PROPERTIES COMPILE_FLAGS "-DFVSIZE=5")
+target_link_libraries(testfconstruct_fail2 "dunecommon")
+add_executable("tuplestest_config" tuplestest.cc)
+add_executable("tuplestest_dune" tuplestest.cc)
+set_target_properties(tuplestest_dune PROPERTIES COMPILE_FLAGS "-DDISABLE_TR1_TUPLE -DDISABLE_STD_TUPLE")
+add_executable("tuplestest_tr1" tuplestest.cc)
+set_target_properties(tuplestest_tr1 PROPERTIES COMPILE_FLAGS "-DDISABLE_STD_TUPLE")
+add_executable("tupleutilitytest" tupleutilitytest.cc)
+add_executable("utilitytest" utilitytest.cc)
+
+# Add the tests to be executed
+foreach(_TEST ${TESTPROGS})
+ add_test(${_TEST} ${_TEST})
+endforeach(_TEST)
+
+#Set properties for failing tests
+set_tests_properties(
+ ${FAILTESTS}
+ PROPERTIES WILL_FAIL true)
+
+# compile tests that should fail
+foreach(_TEST ${COMPILEFAILTESTS})
+ add_test(NAME ${_TEST}
+ COMMAND ${CMAKE_COMMAND} --build . --target ${_TEST} --config $<CONFIGURATION>)
+endforeach(_TEST)
+set_tests_properties(
+ ${COMPILEFAILTESTS}
+ PROPERTIES WILL_FAIL true)
+
+
--- /dev/null
+# -*- tab-width: 4; indent-tabs-mode: nil -*-
+# $Id$
+
+TESTPROGS = \
+ arraylisttest \
+ arraytest \
+ bigunsignedinttest \
+ bitsetvectortest \
+ check_fvector_size \
+ conversiontest \
+ diagonalmatrixtest \
+ dynmatrixtest \
+ dynvectortest \
+ eigenvaluestest \
+ enumsettest \
+ fassigntest \
+ fmatrixtest \
+ fvectortest \
+ gcdlcmtest \
+ iteratorfacadetest \
+ iteratorfacadetest2 \
+ lrutest \
+ mpicollectivecommunication \
+ mpiguardtest \
+ mpihelpertest \
+ mpihelpertest2 \
+ nullptr-test \
+ pathtest \
+ parametertreetest \
+ poolallocatortest \
+ shared_ptrtest_config \
+ shared_ptrtest_dune \
+ singletontest \
+ static_assert_test \
+ streamtest \
+ testdebugallocator \
+ testdebugallocator_fail1 \
+ testdebugallocator_fail2 \
+ testdebugallocator_fail3 \
+ testdebugallocator_fail4 \
+ testdebugallocator_fail5 \
+ testfassign1 \
+ testfassign2 \
+ testfassign3 \
+ testfassign4 \
+ testfassign_fail1 \
+ testfassign_fail2 \
+ testfassign_fail3 \
+ testfassign_fail4 \
+ testfassign_fail5 \
+ testfassign_fail6 \
+ testfconstruct \
+ testfloatcmp \
+ tuplestest_dune \
+ tuplestest_std \
+ tuplestest_tr1 \
+ tupleutilitytest \
+ typetraitstest \
+ utilitytest
+
+# which tests to run
+COMPILE_XFAIL=$(DUNE_COMMON_BIN)/xfail-compile-tests
+
+COMPILE_XFAIL_TESTS = \
+ check_fvector_size_fail1 \
+ check_fvector_size_fail2 \
+ genericiterator_compile_fail \
+ nullptr-test-fail \
+ static_assert_test_fail \
+ testfconstruct_fail1 \
+ testfconstruct_fail2
+
+compile_XFAIL:
+ for i in $(COMPILE_XFAIL_TESTS); do \
+ if $(MAKE) $$i; then \
+ echo "ERROR: target $$i did compile, although it is listed in the COMPILE_XFAIL_TESTS"; \
+ exit 1; \
+ else true; \
+ fi; \
+ done
+
+EXTRA_PROGRAMS = $(COMPILE_XFAIL_TESTS) sllisttest
+
+TESTS = $(TESTPROGS) $(COMPILE_XFAIL)
+
+XFAIL_TESTS = \
+ testdebugallocator_fail1 \
+ testdebugallocator_fail2 \
+ testdebugallocator_fail3 \
+ testdebugallocator_fail4 \
+ testdebugallocator_fail5 \
+ testfassign_fail1 \
+ testfassign_fail2 \
+ testfassign_fail3 \
+ testfassign_fail4 \
+ testfassign_fail5 \
+ testfassign_fail6
+
+# programs just to build when "make check" is used
+check_PROGRAMS = $(TESTPROGS)
+
+noinst_HEADERS = dummyiterator.hh iteratorfacadetest.hh
+
+# Install some test headers, because they get used by tests in other modules
+testincludedir = $(includedir)/dune/common/test
+testinclude_HEADERS = checkmatrixinterface.hh iteratortest.hh
+
+# define the programs (in alphabetical order)
+arraylisttest_SOURCES = arraylisttest.cc
+
+arraytest_SOURCES = arraytest.cc
+
+bigunsignedinttest_SOURCES=bigunsignedinttest.cc
+bigunsignedinttest_CPPFLAGS = $(AM_CPPFLAGS) $(BOOST_CPPFLAGS)
+
+bitsetvectortest_SOURCES = bitsetvectortest.cc
+
+check_fvector_size_fail1_SOURCES = check_fvector_size_fail.cc
+check_fvector_size_fail1_CPPFLAGS = $(AM_CPPFLAGS) -DDIM=1
+
+check_fvector_size_fail2_SOURCES = check_fvector_size_fail.cc
+check_fvector_size_fail2_CPPFLAGS = $(AM_CPPFLAGS) -DDIM=3
+
+check_fvector_size_SOURCES = check_fvector_size.cc
+
+conversiontest_SOURCES = conversiontest.cc
+
+diagonalmatrixtest_SOURCES = diagonalmatrixtest.cc
+
+dynmatrixtest_SOURCES = dynmatrixtest.cc
+
+dynvectortest_SOURCES = dynvectortest.cc
+
+eigenvaluestest_SOURCES = eigenvaluestest.cc
+eigenvaluestest_LDADD = $(LAPACK_LIBS) $(LDADD) $(BLAS_LIBS) $(LIBS) $(FLIBS)
+
+enumsettest_SOURCES = enumsettest.cc
+
+fassigntest_SOURCES = fassigntest.cc
+
+fmatrixtest_SOURCES = fmatrixtest.cc
+fmatrixtest_LDADD = $(LAPACK_LIBS) $(LDADD) $(BLAS_LIBS) $(LIBS) $(FLIBS)
+
+fvectortest_SOURCES = fvectortest.cc
+
+gcdlcmtest_SOURCES = gcdlcmtest.cc
+
+genericiterator_compile_fail_SOURCES = genericiterator_compile_fail.cc
+
+# mention headers so that they are distributed too
+iteratorfacadetest_SOURCES = iteratorfacadetest.cc iteratorfacadetest.hh \
+ iteratortest.hh
+
+iteratorfacadetest2_SOURCES = iteratorfacadetest2.cc
+
+lrutest_SOURCES = lrutest.cc
+
+mpicollectivecommunication_SOURCES = mpicollectivecommunication.cc
+mpicollectivecommunication_CPPFLAGS = $(AM_CPPFLAGS) $(DUNEMPICPPFLAGS)
+mpicollectivecommunication_LDADD = $(DUNEMPILIBS) $(LDADD)
+mpicollectivecommunication_LDFLAGS = $(AM_LDFLAGS) $(DUNEMPILDFLAGS)
+
+mpiguardtest_SOURCES = mpiguardtest.cc
+mpiguardtest_CPPFLAGS = $(AM_CPPFLAGS) $(DUNEMPICPPFLAGS)
+mpiguardtest_LDADD = $(DUNEMPILIBS) $(LDADD)
+mpiguardtest_LDFLAGS = $(AM_LDFLAGS) $(DUNEMPILDFLAGS)
+
+mpihelpertest_SOURCES = mpihelpertest.cc
+mpihelpertest_CPPFLAGS = $(AM_CPPFLAGS) $(DUNEMPICPPFLAGS)
+mpihelpertest_LDADD = $(DUNEMPILIBS) $(LDADD)
+mpihelpertest_LDFLAGS = $(AM_LDFLAGS) $(DUNEMPILDFLAGS)
+
+mpihelpertest2_SOURCES = mpihelpertest.cc
+mpihelpertest2_CPPFLAGS = $(AM_CPPFLAGS) $(DUNEMPICPPFLAGS) -DMPIHELPER_PREINITIALIZE
+mpihelpertest2_LDADD = $(DUNEMPILIBS) $(LDADD)
+mpihelpertest2_LDFLAGS = $(AM_LDFLAGS) $(DUNEMPILDFLAGS)
+
+nullptr_test_SOURCES = nullptr-test.cc nullptr-test2.cc
+nullptr_test_fail_SOURCES = nullptr-test.cc
+nullptr_test_fail_CPPFLAGS = $(AM_CPPFLAGS) -DFAIL
+
+parametertreetest_SOURCES = parametertreetest.cc
+
+pathtest_SOURCES = pathtest.cc
+
+poolallocatortest_SOURCES = poolallocatortest.cc
+
+shared_ptrtest_config_SOURCES = shared_ptrtest.cc
+
+shared_ptrtest_dune_SOURCES = shared_ptrtest.cc
+shared_ptrtest_dune_CPPFLAGS = $(AM_CPPFLAGS) \
+ -DDISABLE_CONFIGURED_SHARED_PTR
+
+singletontest_SOURCES = singletontest.cc
+
+sllisttest_SOURCES = sllisttest.cc
+
+sourcescheck_NOSOURCES = timing.cc
+
+static_assert_test_SOURCES = static_assert_test.cc
+static_assert_test_fail_SOURCES = static_assert_test_fail.cc
+
+streamtest_SOURCES = streamtest.cc
+
+testdebugallocator_SOURCES = testdebugallocator.cc
+testdebugallocator_CPPFLAGS = $(AM_CPPFLAGS)
+
+testdebugallocator_fail1_SOURCES = testdebugallocator.cc
+testdebugallocator_fail1_CPPFLAGS = $(AM_CPPFLAGS) -DFAILURE1
+
+testdebugallocator_fail2_SOURCES = testdebugallocator.cc
+testdebugallocator_fail2_CPPFLAGS = $(AM_CPPFLAGS) -DFAILURE2
+
+testdebugallocator_fail3_SOURCES = testdebugallocator.cc
+testdebugallocator_fail3_CPPFLAGS = $(AM_CPPFLAGS) -DFAILURE3
+
+testdebugallocator_fail4_SOURCES = testdebugallocator.cc
+testdebugallocator_fail4_CPPFLAGS = $(AM_CPPFLAGS) -DFAILURE4 -DDEBUG_ALLOCATOR_KEEP=1
+
+testdebugallocator_fail5_SOURCES = testdebugallocator.cc
+testdebugallocator_fail5_CPPFLAGS = $(AM_CPPFLAGS) -DFAILURE5
+
+testfassign1_SOURCES = testfassign.cc testfassign2.cc
+testfassign1_CPPFLAGS = $(AM_CPPFLAGS) -D_DUNE_TEST_N=3 -D_VALUES="1,2,3"
+
+testfassign2_SOURCES = testfassign.cc
+testfassign2_CPPFLAGS = $(AM_CPPFLAGS) -D_DUNE_TEST_N=3 -D_VALUES="1,zero"
+
+testfassign3_SOURCES = testfassign.cc
+testfassign3_CPPFLAGS = $(AM_CPPFLAGS) -D_DUNE_TEST_N=3 -D_VALUES="zero"
+
+testfassign4_SOURCES = testfassign.cc
+testfassign4_CPPFLAGS = $(AM_CPPFLAGS) -D_DUNE_TEST_N=2 -D_DUNE_TEST_M=3 -D_VALUES="1,zero,nextRow,2,3,4"
+
+testfassign_fail1_SOURCES = testfassign.cc
+testfassign_fail1_CPPFLAGS = $(AM_CPPFLAGS) -D_DUNE_TEST_N=3 -D_VALUES="1,2"
+
+testfassign_fail2_SOURCES = testfassign.cc
+testfassign_fail2_CPPFLAGS = $(AM_CPPFLAGS) -D_DUNE_TEST_N=3 -D_VALUES="1,2,3,4"
+
+testfassign_fail3_SOURCES = testfassign.cc
+testfassign_fail3_CPPFLAGS = $(AM_CPPFLAGS) -D_DUNE_TEST_N=2 -D_DUNE_TEST_M=2 -D_VALUES="1,nextRow,2,3"
+
+testfassign_fail4_SOURCES = testfassign.cc
+testfassign_fail4_CPPFLAGS = $(AM_CPPFLAGS) -D_DUNE_TEST_N=2 -D_DUNE_TEST_M=2 -D_VALUES="1,2,3,nextRow,2,3"
+
+testfassign_fail5_SOURCES = testfassign.cc
+testfassign_fail5_CPPFLAGS = $(AM_CPPFLAGS) -D_DUNE_TEST_N=2 -D_DUNE_TEST_M=2 -D_VALUES="1,2"
+
+testfassign_fail6_SOURCES = testfassign.cc
+testfassign_fail6_CPPFLAGS = $(AM_CPPFLAGS) -D_DUNE_TEST_N=2 -D_DUNE_TEST_M=2 -D_VALUES="1,2,nextRow,2,3,nextRow,4,5"
+
+testfconstruct_SOURCES = testfconstruct.cc
+testfconstruct_CPPFLAGS = $(AM_CPPFLAGS) -DFVSIZE=3
+
+testfconstruct_fail1_SOURCES = testfconstruct.cc
+testfconstruct_fail1_CPPFLAGS = $(AM_CPPFLAGS) -DFVSIZE=2
+
+testfconstruct_fail2_SOURCES = testfconstruct.cc
+testfconstruct_fail2_CPPFLAGS = $(AM_CPPFLAGS) -DFVSIZE=5
+
+testfloatcmp_SOURCES = testfloatcmp.cc
+
+tuplestest_dune_SOURCES = tuplestest.cc
+tuplestest_dune_CPPFLAGS = $(AM_CPPFLAGS) \
+ -DDISABLE_TR1_TUPLE -DDISABLE_STD_TUPLE
+
+tuplestest_std_SOURCES = tuplestest.cc
+
+tuplestest_tr1_SOURCES = tuplestest.cc
+tuplestest_tr1_CPPFLAGS = $(AM_CPPFLAGS) \
+ -DDISABLE_STD_TUPLE
+
+tupleutilitytest_SOURCES = tupleutilitytest.cc
+
+typetraitstest_SOURCES = typetraitstest.cc
+
+utilitytest_SOURCES = utilitytest.cc
+
+
+
+include $(top_srcdir)/am/global-rules
+
+EXTRA_DIST = CMakeLists.txt dummy.f
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <dune/common/arraylist.hh>
+#include <dune/common/test/iteratortest.hh>
+#include <iostream>
+#include <cstdlib>
+#include <algorithm>
+
+class Double {
+public:
+ double val;
+ Double() : val(0){}
+ Double(double d) : val(d){}
+ Double& operator=(double d){
+ val=d;
+ return *this;
+ }
+};
+
+bool operator<(Double a, Double b){
+ return a.val<b.val;
+}
+
+template<class T, int size>
+void randomizeList(Dune::ArrayList<T,size>& alist){
+ using namespace Dune;
+
+ srand(300);
+
+ int lowest=0, highest=1000, range=(highest-lowest)+1;
+
+ for(int i=0; i < 250; i++)
+ alist.push_back(T(static_cast<int>(range*(rand()/(RAND_MAX+1.0)))));
+}
+
+int testSorting(){
+ using namespace Dune;
+ ArrayList<double,10> alist;
+
+ randomizeList(alist);
+ std::sort(alist.begin(), alist.end());
+ double last=-1;
+
+ for(ArrayList<double,10>::iterator iter=alist.begin(), end=alist.end();
+ iter != end; ++iter) {
+ if((*iter)>=last) {
+ last=*iter;
+ }else{
+ std::cerr << last<<">"<<(*iter)<<" List is not sorted! "<<__FILE__ <<":"<<__LINE__<<std::endl;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+template<int size>
+void initConsecutive(Dune::ArrayList<double,size>& alist){
+ using namespace Dune;
+
+ for(int i=0; i < 100; i++)
+ alist.push_back(i);
+}
+
+int testIteratorRemove(){
+ using namespace Dune;
+ ArrayList<double,10> alist;
+ initConsecutive(alist);
+ ArrayList<double,10>::iterator iter=alist.begin();
+
+ iter+=8;
+
+ iter.eraseToHere();
+ ++iter;
+
+ if((*iter)!=10) {
+ std::cerr<<"Removing from iterator failed! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ return 1;
+ }
+
+ iter = alist.begin();
+
+ if((*iter)!=9) {
+ std::cerr<<"Removing from iterator failed! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ return 1;
+ }
+
+ iter +=3;
+ iter.eraseToHere();
+ iter +=4;
+
+ if((*iter)!=17) {
+ std::cerr<<"Removing from iterator failed! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ return 1;
+ }
+
+ alist.purge();
+ if(*(alist.begin())!=13) {
+ std::cerr<<"Purging iterator failed! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ return 1;
+ }
+ return 0;
+}
+int testRandomAccess(){
+ using namespace Dune;
+ ArrayList<double,10> alist;
+ initConsecutive(alist);
+
+ ArrayList<double,10>::iterator iter=alist.begin();
+
+
+ for(int i=0; i < 100; i++) {
+ if(iter[i]!=i) {
+ std::cerr << "Random Access failed: "<<iter[i]<<"!="<<i<<" "<< __FILE__ <<":"<<__LINE__<<std::endl;
+ return 1;
+ }
+
+ if(*(iter+i)!=i) {
+ std::cerr << "Random Access failed "<< __FILE__ <<":"<<__LINE__<<std::endl;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int testComparison(){
+ using namespace Dune;
+ ArrayList<double,10> alist;
+ initConsecutive(alist);
+
+ ArrayList<double,10>::iterator iter=alist.begin(), iter1=alist.begin();
+ iter1=iter+5;
+ iter1=iter-5;
+ iter1=iter+5;
+
+
+ if(!(iter<iter1)) {
+ std::cerr<<*iter<<">="<<*iter1<<" Operator< seems to be wrong! "<< __FILE__ <<__LINE__<<std::endl;
+ return 1;
+ }
+
+ if(!(iter1>iter)) {
+ std::cerr<<"operator> seems to be wrong! "<< __FILE__ <<__LINE__<<std::endl;
+ return 1;
+ }
+
+ if(!(iter<=iter1)) {
+ std::cerr<<"operator<= seems to be wrong! "<< __FILE__ <<__LINE__<<std::endl;
+ return 1;
+ }
+
+ if(!(iter1>=iter)) {
+ std::cerr<<"operator>= seems to be wrong! "<< __FILE__ <<__LINE__<<std::endl;
+ return 1;
+ }
+
+ if(!(iter1 != iter)) {
+ std::cerr<<"operator!= seems to be wrong! "<< __FILE__ <<__LINE__<<std::endl;
+ return 1;
+ }
+
+ if(!(iter1 == iter+5)) {
+ std::cerr<<"operator== seems to be wrong! "<< __FILE__ <<__LINE__<<std::endl;
+ return 1;
+ }
+ return 0;
+}
+
+
+int main(){
+ using namespace Dune;
+ using namespace std;
+ ArrayList<double,100> alist;
+
+ randomizeList(alist);
+
+ int ret=testIterator(alist);
+
+ if(0!=testComparison()) {
+ ret++;
+ cerr<< "Comparison failed!"<<endl;
+ }
+
+ if(0!=testRandomAccess()) {
+ ret++;
+ cerr<< "Ransom Access failed!"<<endl;
+ }
+
+ if(0!=testSorting()) {
+ ret++;
+ cerr<< "Sorting failed!"<<endl;
+ }
+
+ if(0!=testIteratorRemove()) {
+ ret++;
+ cerr<< "Erasing failed!"<<endl;
+ }
+ return ret;
+
+}
--- /dev/null
+// -*- 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 <cstddef>
+#include <iostream>
+#include <ostream>
+
+#include <dune/common/array.hh>
+#include <dune/common/classname.hh>
+#include <dune/common/fvector.hh>
+
+template<class T, std::size_t n>
+void f(const Dune::array<T, n> &a) {
+ std::cout << "Got a " << Dune::className(a) << " with elements";
+ for(std::size_t i = 0; i < n; ++i)
+ std::cout << " (" << a[i] << ")";
+ std::cout << std::endl;
+}
+
+int main() {
+ // check that make_array works
+ f(Dune::make_array(1, 2));
+
+ Dune::FieldVector<double, 2> x(0);
+ f(Dune::make_array(x, x));
+}
--- /dev/null
+// -*- 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 <dune/common/bigunsignedint.hh>
+#include <limits>
+#include <iostream>
+
+#if HAVE_BOOST_HASH
+#include <boost/functional/hash.hpp>
+#endif
+
+int main()
+{
+
+ std::cout<<"unsigned short: max="<<std::numeric_limits<unsigned short>::max()
+ <<" min="<<std::numeric_limits<unsigned short>::min()
+ <<" digits="<<std::numeric_limits<unsigned short>::digits<<std::endl;
+ std::cout<<"int: max="<<std::numeric_limits<int>::max()<<" min="
+ <<std::numeric_limits<int>::min()<<" digits="
+ <<std::numeric_limits<int>::digits<<std::endl;
+ std::cout<<"unsigned int: max="<<std::numeric_limits<unsigned int>::max()
+ <<" min="<<std::numeric_limits<unsigned int>::min()<<" digits="
+ <<std::numeric_limits<unsigned int>::digits<<" digits10="
+ <<std::numeric_limits<unsigned int>::digits10<<" radix="
+ <<std::numeric_limits<unsigned int>::radix<<" eps="
+ <<std::numeric_limits<unsigned int>::epsilon()
+ <<" round_error="
+ <<std::numeric_limits<unsigned int>::round_error()
+ <<" min_exponent="
+ <<std::numeric_limits<unsigned int>::min_exponent
+ <<" float_denorm_style="
+ <<std::numeric_limits<unsigned int>::has_denorm
+ <<" traps="<<std::numeric_limits<unsigned int>::traps
+ <<std::endl;
+ std::cout<<"bigunsignedint: max="<<std::numeric_limits<Dune::bigunsignedint<32> >::max()
+ <<" min="<<std::numeric_limits<Dune::bigunsignedint<32> >::min()<<" digits="<<std::numeric_limits<Dune::bigunsignedint<32> >::digits<<std::endl;
+ std::cout<<"bigunsignedint: max="<<std::numeric_limits<Dune::bigunsignedint<100> >::max()
+ <<" min="<<std::numeric_limits<Dune::bigunsignedint<100> >::min()<<" digits="<<std::numeric_limits<Dune::bigunsignedint<100> >::digits
+ <<" traps="<<std::numeric_limits<Dune::bigunsignedint<100> >::traps
+ <<std::endl;
+
+ int a1, b1, c1;
+ a1=100;
+ b1=3;
+ c1=a1/b1;
+ std::cout<<a1<<"/"<<b1<<"="<<c1<<std::endl;
+
+
+ Dune::bigunsignedint<100> a, b, c;
+ a=100;
+ b=3;
+ c=a/b;
+ std::cout<<a<<"/"<<b<<"="<<c<<std::endl;
+
+ try{
+
+ a=100;
+ b=0;
+ c=a/1;
+ std::cout<<a1<<"/"<<b1<<"="<<c1<<std::endl;
+ a=1000000;
+ std::cout<<a.todouble()<<std::endl;
+ std::cout<<a.touint()<<std::endl;
+ b=a;
+ a=a*b*b;
+ std::cout<<a.todouble()<<std::endl;
+
+#if HAVE_DUNE_HASH
+
+ {
+ Dune::hash<Dune::bigunsignedint<100> > hasher;
+ std::cout << "Dune::hash: " << hasher(a) << std::endl;
+ }
+
+#if HAVE_STD_HASH
+ {
+ std::hash<Dune::bigunsignedint<100> > hasher;
+ std::cout << "std::hash: " << hasher(a) << std::endl;
+ }
+#endif
+
+#if HAVE_TR1_HASH
+ {
+ std::tr1::hash<Dune::bigunsignedint<100> > hasher;
+ std::cout << "std::tr1::hash: " << hasher(a) << std::endl;
+ }
+#endif
+
+#if HAVE_BOOST_HASH
+ {
+ boost::hash<Dune::bigunsignedint<100> > hasher;
+ std::cout << "boost::hash: " << hasher(a) << std::endl;
+ }
+#endif
+
+#endif // HAVE_DUNE_HASH
+
+ }
+ catch(Dune::MathError e) {
+ std::cout<<e<<std::endl;
+ }
+}
--- /dev/null
+// -*- 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 <dune/common/bitsetvector.hh>
+#if defined(__GNUC__) && ! defined(__clang__)
+#include <ext/malloc_allocator.h>
+#endif
+
+#include <dune/common/test/iteratortest.hh>
+
+template<class BBF>
+struct ConstReferenceOp
+{
+ typedef typename BBF::value_type bitset;
+ typedef typename BBF::const_reference const_reference;
+
+ void operator()(const_reference t){
+ bitset x = t[0];
+ }
+};
+
+template <class T>
+void testConstBitSetMethods(const T t)
+{
+ t.size();
+ t[0];
+ t[t.size()-1];
+ t << 2;
+ t >> 2;
+ ~t;
+ t.count();
+ t.any();
+ t.none();
+ t.test(0);
+}
+
+template<class BBF>
+void testContainer(BBF & bbf)
+{
+ typedef typename BBF::value_type bitset;
+ typedef typename BBF::reference reference;
+ typedef typename BBF::const_reference const_reference;
+
+ const BBF & cbbf = bbf;
+
+ bitset x = bbf[3];
+ reference y = bbf[4];
+ const_reference z = bbf[4];
+ const reference v = bbf[4];
+
+ // assignement
+ y = false;
+ y[2] = true;
+ y = x;
+ y = z;
+ y = v;
+ x = y;
+ x = z;
+ x = v;
+ y = cbbf[1];
+ x = cbbf[1];
+ bbf[4] = x;
+ bbf[4] = v;
+ bbf[4] = y;
+ bbf[4] = true;
+
+ // invoke methods
+ testConstBitSetMethods(x);
+ testConstBitSetMethods(y);
+ testConstBitSetMethods(z);
+ testConstBitSetMethods(v);
+ testConstBitSetMethods(bbf[1]);
+ testConstBitSetMethods(cbbf[2]);
+
+ // equality
+ y == cbbf[2];
+ y == bbf[3];
+ y == x;
+ x == y;
+ x == z;
+ z == x;
+ z == y;
+ y == z;
+
+ // inequality
+ y != cbbf[2];
+ y != bbf[3];
+ y != x;
+ x != y;
+ x != z;
+ z != x;
+ z != y;
+ y != z;
+
+ // &=
+ y &= cbbf[2];
+ y &= bbf[3];
+ y &= x;
+ x &= y;
+ x &= z;
+ y &= z;
+
+ // |=
+ y |= cbbf[2];
+ y |= bbf[3];
+ y |= x;
+ x |= y;
+ x |= z;
+ y |= z;
+
+ // ^=
+ y ^= cbbf[2];
+ y ^= bbf[3];
+ y ^= x;
+ x ^= y;
+ x ^= z;
+ y ^= z;
+
+ // shift operator
+ y <<= 1;
+ y >>= 1;
+
+ // flip
+ y.flip();
+ y.flip(2);
+ y[3].flip();
+}
+
+template<class BBF>
+void testConstContainer(const BBF& bbf){
+ typedef typename BBF::value_type bitset;
+ typedef typename BBF::iterator iterator;
+ typedef typename std::iterator_traits<iterator>::value_type value_type;
+ typedef typename BBF::const_reference reference;
+
+ const BBF & cbbf = bbf;
+
+ bitset x = bbf[3];
+ value_type z;
+ reference y = bbf[4];
+
+ // assignement
+ x = y;
+ x = cbbf[1];
+
+ // equality
+ y == cbbf[2];
+ y == bbf[3];
+ y == x;
+ x == y;
+
+ // inequality
+ y != cbbf[2];
+ y != bbf[3];
+ y != x;
+ x != y;
+}
+
+template<int block_size, class Alloc>
+void doTest() {
+ typedef Dune::BitSetVector<block_size, Alloc> BBF;
+
+ BBF bbf(10,true);
+ const BBF & cbbf = bbf;
+
+ // test containers and some basic bitset operations
+ testContainer(bbf);
+ testConstContainer(bbf);
+ testConstContainer(cbbf);
+
+ // iterator interface
+#ifndef NDEBUG
+ ConstReferenceOp<BBF> cop;
+ assert(testIterator(bbf, cop) == 0);
+ assert(testIterator(cbbf, cop) == 0);
+#endif
+}
+
+int main()
+{
+ doTest<4, std::allocator<bool> >();
+#if defined(__GNUC__) && ! defined(__clang__)
+ doTest<4, __gnu_cxx::malloc_allocator<bool> >();
+#endif
+ return 0;
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#include <config.h>
+#include <dune/common/dynvector.hh>
+
+int main(int, char **)
+{
+
+ Dune::DynamicVector<double> one(1);
+ Dune::DynamicVector<double> two(2);
+
+ two = one;
+
+ return 0;
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#include <config.h>
+#include <dune/common/fvector.hh>
+
+int main(int argc, char * argv[])
+{
+
+ Dune::FieldVector<double,DIM> one(1);
+ Dune::FieldVector<float,2> two(2);
+
+ one=two;
+
+ return 0;
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_COMMON_CHECK_MATRIX_INTERFACE_HH
+#define DUNE_COMMON_CHECK_MATRIX_INTERFACE_HH
+
+#include <algorithm>
+#include <limits>
+
+#include <dune/common/dynvector.hh>
+#include <dune/common/exceptions.hh>
+#include <dune/common/ftraits.hh>
+#include <dune/common/fvector.hh>
+
+
+/*
+ * @file
+ * @brief This file provides an interface check for dense matrices.
+ * @author Christoph Gersbacher
+ */
+
+
+namespace Dune
+{
+
+ // External forward declarations for namespace Dune
+ // ------------------------------------------------
+
+ template< class, int, int > class FieldMatrix;
+ template< class, int > class DiagonalMatrix;
+
+} // namespace Dune
+
+
+
+namespace CheckMatrixInterface
+{
+
+ namespace Capabilities
+ {
+
+ // hasStaticSizes
+ // --------------
+
+ template< class Matrix >
+ struct hasStaticSizes
+ {
+ static const bool v = false;
+ static const int rows = ~0;
+ static const int cols = ~0;
+ };
+
+ template< class Matrix >
+ struct hasStaticSizes< const Matrix >
+ {
+ static const bool v = hasStaticSizes< Matrix >::v;
+ static const int rows = hasStaticSizes< Matrix >::rows;
+ static const int cols = hasStaticSizes< Matrix >::cols;
+ };
+
+
+
+ // isSquare
+ // --------
+
+ template< class Matrix >
+ struct isSquare
+ {
+ static const bool v = false;
+ };
+
+ template< class Matrix >
+ struct isSquare< const Matrix >
+ {
+ static const bool v = isSquare< Matrix >::v;
+ };
+
+
+
+ // Template specializations for Dune::FieldMatrix
+ // ----------------------------------------------
+
+ template< class K, int r, int c >
+ struct hasStaticSizes< Dune::FieldMatrix< K, r, c > >
+ {
+ static const bool v = true;
+ static const int rows = r;
+ static const int cols = c;
+ };
+
+ template< class K, int rows, int cols >
+ struct isSquare< Dune::FieldMatrix< K, rows, cols > >
+ {
+ static const bool v = ( rows == cols );
+ };
+
+
+
+ // Template specializations for Dune::DiagonalMatrix
+ // -------------------------------------------------
+
+ template< class K, int n >
+ struct hasStaticSizes< Dune::DiagonalMatrix<K,n> >
+ {
+ static const bool v = true;
+ static const int rows = n;
+ static const int cols = n;
+ };
+
+ template< class K, int n >
+ struct isSquare< Dune::DiagonalMatrix<K,n> >
+ {
+ static const bool v = true;
+ };
+
+ } // namespace Capabilities
+
+
+
+ // UseDynamicVector
+ // ----------------
+
+ template< class Matrix >
+ struct UseDynamicVector
+ {
+ typedef typename Matrix::value_type value_type;
+
+ typedef Dune::DynamicVector< value_type > domain_type;
+ typedef domain_type range_type;
+
+ static domain_type domain ( const Matrix &matrix, value_type v = value_type() )
+ {
+ return domain_type( matrix.M(), v );
+ }
+
+ static range_type range ( const Matrix &matrix, value_type v = value_type() )
+ {
+ return range_type( matrix.N(), v );
+ }
+ };
+
+
+
+ // UseFieldVector
+ // --------------
+
+ template< class K, int rows, int cols >
+ struct UseFieldVector
+ {
+ typedef K value_type;
+
+ typedef Dune::FieldVector< K, cols > domain_type;
+ typedef Dune::FieldVector< K, rows > range_type;
+
+ template< class Matrix >
+ static domain_type domain ( const Matrix &, value_type v = value_type() )
+ {
+ return domain_type( v );
+ }
+
+ template< class Matrix >
+ static range_type range ( const Matrix &, value_type v = value_type() )
+ {
+ return range_type( v );
+ }
+ };
+
+
+
+ // MatrixSizeHelper
+ // ----------------
+
+ template< class Matrix, bool hasStaticSizes = Capabilities::hasStaticSizes< Matrix >::v >
+ struct MatrixSizeHelper;
+
+ template< class Matrix >
+ struct MatrixSizeHelper< Matrix, false >
+ {
+ typedef typename Matrix::size_type size_type;
+ static const size_type rows ( const Matrix &matrix ) { return matrix.rows(); }
+ static const size_type cols ( const Matrix &matrix ) { return matrix.cols(); }
+ };
+
+ template< class Matrix >
+ struct MatrixSizeHelper< Matrix, true >
+ {
+ typedef typename Matrix::size_type size_type;
+ static const size_type rows ( const Matrix & ) { return Matrix::rows; }
+ static const size_type cols ( const Matrix & ) { return Matrix::cols; }
+ };
+
+
+
+ // CheckIfSquareMatrix
+ // -------------------
+
+ template< class Matrix, class Traits, bool isSquare = Capabilities::isSquare< Matrix >::v >
+ struct CheckIfSquareMatrix;
+
+ template< class Matrix, class Traits >
+ struct CheckIfSquareMatrix< Matrix, Traits, false >
+ {
+ static void apply ( const Matrix &) {}
+
+ static void apply ( Matrix &) {}
+ };
+
+ template< class Matrix, class Traits >
+ struct CheckIfSquareMatrix< Matrix, Traits, true >
+ {
+ typedef typename Matrix::value_type value_type;
+
+ static value_type tolerance ()
+ {
+ return value_type( 16 ) * std::numeric_limits< value_type >::epsilon();
+ }
+
+ static void apply ( const Matrix &matrix )
+ {
+ const value_type determinant = matrix.determinant();
+ if( determinant > tolerance() )
+ {
+ typename Traits::domain_type x = Traits::domain( matrix );
+ const typename Traits::range_type b = Traits::range( matrix );
+ matrix.solve( x, b );
+ }
+ }
+
+ static void apply ( Matrix &matrix )
+ {
+ apply( const_cast< const Matrix & >( matrix ) );
+ if( matrix.determinant() > tolerance() )
+ matrix.invert();
+ }
+ };
+
+
+
+ // CheckConstMatrix
+ // ----------------
+
+ template< class Matrix, class Traits >
+ struct CheckConstMatrix
+ {
+ // required type definitions
+ typedef typename Matrix::size_type size_type;
+
+ typedef typename Matrix::value_type value_type;
+ typedef typename Matrix::field_type field_type;
+ typedef typename Matrix::block_type block_type;
+
+ typedef typename Matrix::const_row_reference const_row_reference;
+
+ typedef typename Matrix::ConstIterator ConstIterator;
+
+ static void apply ( const Matrix &matrix )
+ {
+ checkDataAccess ( matrix );
+ checkIterators ( matrix );
+ checkLinearAlgebra ( matrix );
+ checkNorms ( matrix );
+ checkSizes ( matrix );
+ CheckIfSquareMatrix< Matrix, Traits >::apply( matrix );
+
+ // TODO: check comparison
+ // bool operator == ( const Matrix &other );
+ // bool operator != ( const Matrix &other );
+ }
+
+ // check size methods
+ static void checkSizes ( const Matrix &matrix )
+ {
+ DUNE_UNUSED const size_type size = matrix.size();
+ const size_type rows = MatrixSizeHelper< Matrix >::rows( matrix );
+ const size_type cols = MatrixSizeHelper< Matrix >::cols( matrix );
+ const size_type N = matrix.N();
+ const size_type M = matrix.M();
+
+ if( N != rows || M != cols )
+ DUNE_THROW( Dune::RangeError, "Returned inconsistent sizes." );
+ }
+
+ // check read-only access to data
+ static void checkDataAccess ( const Matrix &matrix )
+ {
+ const size_type size = matrix.size();
+ for( size_type i = size_type( 0 ); i < size; ++i )
+ DUNE_UNUSED const_row_reference row = matrix[ i ];
+
+ const size_type rows = MatrixSizeHelper< Matrix >::rows( matrix );
+ const size_type cols = MatrixSizeHelper< Matrix >::cols( matrix );
+ for( size_type i = size_type( 0 ); i < rows; ++i )
+ {
+ for( size_type j = size_type( 0 ); j < cols; ++j )
+ {
+ DUNE_UNUSED bool exists = matrix.exists( i, j );
+ DUNE_UNUSED const value_type &value = matrix[ i ][ j ];
+ }
+ }
+ }
+
+ // check norms
+ static void checkNorms ( const Matrix &matrix )
+ {
+ typedef typename Dune::FieldTraits< value_type >::real_type real_type;
+ real_type frobenius_norm = matrix.frobenius_norm();
+ real_type frobenius_norm2 = matrix.frobenius_norm2();
+ real_type infinity_norm = matrix.infinity_norm() ;
+ real_type infinity_norm_real = matrix.infinity_norm_real();
+
+ if( std::min( std::min( frobenius_norm, frobenius_norm2 ),
+ std::min( infinity_norm, infinity_norm_real ) ) < real_type( 0 ) )
+ DUNE_THROW( Dune::InvalidStateException, "Norms must return non-negative value." );
+ }
+
+ // check basic linear algebra methods
+ static void checkLinearAlgebra ( const Matrix &matrix )
+ {
+ typename Traits::domain_type domain = Traits::domain( matrix );
+ typename Traits::range_type range = Traits::range( matrix );
+ typename Traits::value_type alpha( 1 );
+
+ matrix.mv( domain, range );
+ matrix.mtv( range, domain );
+ matrix.umv( domain, range );
+ matrix.umtv( range, domain );
+ matrix.umhv( range, domain );
+ matrix.mmv( domain, range );
+ matrix.mmtv( range, domain );
+ matrix.mmhv( range, domain );
+ matrix.usmv( alpha, domain, range );
+ matrix.usmtv( alpha, range, domain );
+ matrix.usmhv( alpha, range, domain );
+ }
+
+ // check iterator methods
+ static void checkIterators ( const Matrix &matrix )
+ {
+ const ConstIterator end = matrix.end();
+ for( ConstIterator it = matrix.begin(); it != end; ++it )
+ DUNE_UNUSED const_row_reference row = *it;
+ }
+ };
+
+
+
+ // CheckNonConstMatrix
+ // -------------------
+
+ template< class Matrix, class Traits >
+ struct CheckNonConstMatrix
+ {
+ // required type definitions
+ typedef typename Matrix::size_type size_type;
+ typedef typename Matrix::value_type value_type;
+ typedef typename Matrix::row_reference row_reference;
+ typedef typename Matrix::row_type row_type;
+ typedef typename Matrix::Iterator Iterator;
+
+ static void apply ( Matrix &matrix )
+ {
+ checkIterators( matrix );
+ checkAssignment( matrix );
+
+ CheckIfSquareMatrix< Matrix, Traits >::apply( matrix );
+
+ // TODO: check scalar/matrix and matrix/matrix operations
+ // Matrix &operator+= ( const Matrix &other );
+ // Matrix &operator-= ( const Matrix &other );
+ // Matrix &operator*= ( const value_type &v );
+ // Matrix &operator/= ( const value_type &v );
+ // Matrix &axpy += ( const value_type &v, const Matrix &other );
+ // Matrix &axpy += ( const value_type &v, const Matrix &other );
+ // Matrix &leftmultiply ( const Matrix &other );
+ // Matrix &rightmultiply ( const Matrix &other );
+ }
+
+ // check assignment
+ static void checkAssignment ( Matrix &matrix )
+ {
+ matrix = value_type( 1 );
+
+ const size_type size = matrix.size();
+ for( size_type i = size_type( 0 ); i < size; ++i )
+ {
+ row_reference row = matrix[ i ];
+ row = row_type( value_type( 0 ) );
+ }
+
+ const size_type rows = MatrixSizeHelper< Matrix >::rows( matrix );
+ const size_type cols = MatrixSizeHelper< Matrix >::cols( matrix );
+ for( size_type i = size_type( 0 ); i < rows; ++i )
+ {
+ for( size_type j = size_type( 0 ); j < cols; ++j )
+ matrix[ i ][ j ] = ( i == j ? value_type( 1 ) : value_type( 0 ) );
+ }
+ }
+
+ // check iterator methods
+ static void checkIterators ( Matrix &matrix )
+ {
+ const Iterator end = matrix.end();
+ for( Iterator it = matrix.begin(); it != end; ++it )
+ {
+ row_reference row = *it;
+ row = row_type( value_type( 0 ) );
+ }
+ }
+ };
+
+} // namespace CheckMatrixInterface
+
+
+
+namespace Dune
+{
+
+ // checkMatrixInterface
+ // --------------------
+
+ template< class Matrix, class Traits = CheckMatrixInterface::UseDynamicVector< Matrix > >
+ void checkMatrixInterface ( const Matrix &matrix )
+ {
+ CheckMatrixInterface::CheckConstMatrix< Matrix, Traits >::apply( matrix );
+ }
+
+ template< class Matrix, class Traits = CheckMatrixInterface::UseDynamicVector< Matrix > >
+ void checkMatrixInterface ( Matrix &matrix )
+ {
+ checkMatrixInterface( const_cast< const Matrix & >( matrix ) );
+ CheckMatrixInterface::CheckNonConstMatrix< Matrix, Traits >::apply( matrix );
+ }
+
+} // namespace Dune
+
+#endif // #ifndef DUNE_COMMON_CHECK_MATRIX_INTERFACE_HH
--- /dev/null
+// -*- 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/typetraits.hh>
+
+int main ()
+{
+ std :: cout << "Conversion from int to double exists? "
+ << Dune::Conversion< int, double > :: exists << std :: endl;
+
+ return 0;
+}
--- /dev/null
+// -*- 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 <dune/common/diagonalmatrix.hh>
+
+#include <iostream>
+#include <algorithm>
+
+#include <dune/common/fvector.hh>
+#include <dune/common/exceptions.hh>
+
+#include "checkmatrixinterface.hh"
+
+using namespace Dune;
+
+template<class K, int n>
+void test_matrix()
+{
+ typedef typename DiagonalMatrix<K,n>::size_type size_type;
+
+ DiagonalMatrix<K,n> A(1);
+ FieldVector<K,n> f;
+ FieldVector<K,n> v;
+
+ // assign matrix
+ A=2;
+
+ // assign vector
+ f = 1;
+ v = 2;
+
+ // matrix vector product
+ A.umv(v,f);
+
+
+ // test norms
+ A.frobenius_norm();
+ A.frobenius_norm2();
+ A.infinity_norm();
+ A.infinity_norm_real();
+
+ std::sort(v.begin(), v.end());
+
+ // print matrix
+ std::cout << A << std::endl;
+ // print vector
+ std::cout << f << std::endl;
+
+ // assign to FieldMatrix
+ DUNE_UNUSED FieldMatrix<K,n,n> AFM = FieldMatrix<K,n,n>(A);
+ DUNE_UNUSED FieldMatrix<K,n,n> AFM2 = A;
+ DUNE_UNUSED FieldMatrix<K,n,n> AFM3;
+ AFM3 = A;
+}
+
+template<class K, int n>
+void test_interface()
+{
+ typedef CheckMatrixInterface::UseFieldVector<K,n,n> Traits;
+ typedef Dune::DiagonalMatrix<K,n> DiagonalMatrix;
+
+ const DiagonalMatrix A(1);
+ checkMatrixInterface< DiagonalMatrix >( A );
+ checkMatrixInterface< DiagonalMatrix, Traits >( A );
+}
+
+int main()
+{
+ try {
+ test_matrix<float, 1>();
+ test_interface<float, 1>();
+ test_matrix<double, 1>();
+ test_interface<double, 1>();
+ test_matrix<double, 5>();
+ test_interface<double, 5>();
+ }
+ catch (Dune::Exception & e)
+ {
+ std::cerr << "Exception: " << e << std::endl;
+ }
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_COMMON_DUMMYITERATOR_HH
+#define DUNE_COMMON_DUMMYITERATOR_HH
+
+#include <cstddef>
+
+#include <dune/common/iteratorfacades.hh>
+#include <dune/common/typetraits.hh>
+
+template<typename T>
+class dummyiterator
+ : public Dune::BidirectionalIteratorFacade<dummyiterator<T>, T, T&,
+ std::ptrdiff_t>
+{
+ friend class dummyiterator<const typename Dune::remove_const<T>::type>;
+
+ T *value;
+
+public:
+ dummyiterator(T& value_)
+ : value(&value_)
+ {}
+
+ template<typename T2>
+ dummyiterator
+ ( const dummyiterator<T2>& o,
+ typename Dune::enable_if<Dune::Conversion<T2&, T&>::exists>::type* = 0)
+ : value(o.value)
+ {}
+
+ T& derefence() const {
+ return *value;
+ }
+
+ bool equals(const dummyiterator& o) const {
+ return value == o.value;
+ }
+
+ void increment() {}
+ void decrement() {}
+};
+
+#endif // DUNE_COMMON_DUMMYITERATOR_HH
--- /dev/null
+// -*- 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
+// Activate checking
+#ifndef DUNE_ISTL_WITH_CHECKING
+#define DUNE_ISTL_WITH_CHECKING
+#endif
+#include <dune/common/dynmatrix.hh>
+#include <dune/common/dynvector.hh>
+#include <dune/common/fvector.hh>
+#include <iostream>
+#include <algorithm>
+#include <vector>
+
+#include "checkmatrixinterface.hh"
+
+using namespace Dune;
+
+template<typename T, std::size_t n>
+int test_invert_solve(T A_data[n*n], T inv_data[n*n],
+ T x_data[n], T b_data[n])
+{
+ int ret=0;
+
+ std::cout <<"Checking inversion of:"<<std::endl;
+
+ DynamicMatrix<T> A(n,n), inv(n,n), calced_inv(n,n);
+ FieldVector<T,n> x, b, calced_x;
+
+ for(size_t i =0; i < n; ++i) {
+ x[i]=x_data[i];
+ b[i]=b_data[i];
+ for(size_t j=0; j <n; ++j) {
+ A[i][j] = A_data[i*n+j];
+ inv[i][j] = inv_data[i*n+j];
+ }
+ }
+
+ std::cout<<A<<std::endl;
+
+ // Check whether given inverse is correct
+ DynamicMatrix<T> prod = A;
+ prod.rightmultiply(inv);
+ for (size_t i=0; i<n; i++)
+ prod[i][i] -= 1;
+
+ bool equal=true;
+ if (prod.infinity_norm() > 1e-6) {
+ std::cerr<<"Given inverse wrong"<<std::endl;
+ equal=false;
+ }
+
+ DynamicMatrix<T> copy(A);
+ A.invert();
+
+ calced_inv = A;
+ A-=inv;
+
+
+ double singthres = FMatrixPrecision<>::singular_limit()*10;
+ for(size_t i =0; i < n; ++i)
+ for(size_t j=0; j <n; ++j)
+ if(std::abs(A[i][j])>singthres) {
+ std::cerr<<"calculated inverse wrong at ("<<i<<","<<j<<")"<<std::endl;
+ equal=false;
+ }
+
+ if(!equal) {
+ ret++;
+ std::cerr<<"Calculated inverse was:"<<std::endl;
+ std::cerr <<calced_inv<<std::endl;
+ std::cerr<<"Should have been"<<std::endl;
+ std::cerr<<inv << std::endl;
+ }else
+ std::cout<<"Result is"<<std::endl<<calced_inv<<std::endl;
+
+
+ std::cout<<"Checking solution for rhs="<<b<<std::endl;
+
+ // Check whether given solution is correct
+ FieldVector<T,n> trhs=b;
+
+ copy.mmv(x,trhs);
+ equal=true;
+
+ if (trhs.infinity_norm() > 1e-6) {
+ std::cerr<<"Given rhs does not fit solution"<<std::endl;
+ equal=false;
+ }
+ copy.solve(calced_x, b);
+ FieldVector<T,n> xcopy(calced_x);
+ xcopy-=x;
+
+ equal=true;
+
+ for(size_t i =0; i < n; ++i)
+ if(std::abs(xcopy[i])>singthres) {
+ std::cerr<<"calculated isolution wrong at ("<<i<<")"<<std::endl;
+ equal=false;
+ }
+
+ if(!equal) {
+ ret++;
+ std::cerr<<"Calculated solution was:"<<std::endl;
+ std::cerr <<calced_x<<std::endl;
+ std::cerr<<"Should have been"<<std::endl;
+ std::cerr<<x<<std::endl;
+ std::cerr<<"difference is "<<xcopy<<std::endl;
+ }else
+ std::cout<<"Result is "<<calced_x<<std::endl;
+
+ return ret;
+}
+
+
+int test_invert_solve()
+{
+ int ret=0;
+
+ double A_data[9] = {1, 5, 7, 2, 14, 15, 4, 40, 39};
+ double inv_data[9] = {-9.0/4, 85.0/24, -23.0/24, -3.0/4, 11.0/24, -1.0/24, 1, -5.0/6, 1.0/6};
+ double b[3] = {32,75,201};
+ double x[3] = {1,2,3};
+
+ ret += test_invert_solve<double,3>(A_data, inv_data, x, b);
+
+ double A_data0[9] = {-0.5, 0, -0.25, 0.5, 0, -0.25, 0, 0.5, 0};
+ double inv_data0[9] = {-1, 1, 0, 0, 0, 2, -2, -2, 0};
+ double b0[3] = {32,75,201};
+ double x0[3] = {43, 402, -214};
+
+ ret += test_invert_solve<double,3>(A_data0, inv_data0, x0, b0);
+
+ double A_data1[9] = {0, 1, 0, 1, 0, 0, 0, 0, 1};
+ double b1[3] = {0,1,2};
+ double x1[3] = {1,0,2};
+
+ ret += test_invert_solve<double,3>(A_data1, A_data1, x1, b1);
+
+ double A_data2[9] ={3, 1, 6, 2, 1, 3, 1, 1, 1};
+ double inv_data2[9] ={-2, 5, -3, 1, -3, 3, 1, -2, 1};
+ double b2[3] = {2, 7, 4};
+ double x2[3] = {19,-7,-8};
+
+ return ret + test_invert_solve<double,3>(A_data2, inv_data2, x2, b2);
+}
+
+template<class K, class X, class Y>
+void test_mult(DynamicMatrix<K>& A,
+ X& v, Y& f)
+{
+ // test the various matrix-vector products
+ A.mv(v,f);
+ A.mtv(f,v);
+ A.umv(v,f);
+ A.umtv(f,v);
+ A.umhv(f,v);
+ A.mmv(v,f);
+ A.mmtv(f,v);
+ A.mmhv(f,v);
+ A.usmv((K)0.5,v,f);
+ A.usmtv((K)0.5,f,v);
+ A.usmhv((K)0.5,f,v);
+}
+
+
+template<class K, int n, int m>
+void test_matrix()
+{
+ typedef typename DynamicMatrix<K>::size_type size_type;
+
+ DynamicMatrix<K> A(n,m);
+ DynamicVector<K> f(n);
+ DynamicVector<K> v(m);
+
+ // assign matrix
+ A=K();
+ // random access matrix
+ for (size_type i=0; i<n; i++)
+ for (size_type j=0; j<m; j++)
+ A[i][j] = i*j;
+ // iterator matrix
+ typename DynamicMatrix<K>::RowIterator rit = A.begin();
+ for (; rit!=A.end(); ++rit)
+ {
+ rit.index();
+ typename DynamicMatrix<K>::ColIterator cit = rit->begin();
+ for (; cit!=rit->end(); ++cit)
+ {
+ cit.index();
+ (*cit) *= 2;
+ }
+ }
+
+ // assign vector
+ f = 1;
+
+ // random access vector
+ for (size_type i=0; i<v.dim(); i++)
+ v[i] = i;
+ // iterator vector
+ typename DynamicVector<K>::iterator it = v.begin();
+ typename DynamicVector<K>::ConstIterator end = v.end();
+ for (; it!=end; ++it)
+ {
+ it.index();
+ (*it) *= 2;
+ }
+ // reverse iterator vector
+ it = v.beforeEnd();
+ end = v.beforeBegin();
+ for (; it!=end; --it)
+ (*it) /= 2;
+ // find vector
+ for (size_type i=0; i<v.dim(); i++)
+ {
+ it = v.find(i);
+ (*it) += 1;
+ }
+
+ // matrix vector product
+ A.umv(v,f);
+ // check that mv and umv are doing the same thing
+ {
+ DynamicVector<K> res2(n,0);
+ DynamicVector<K> res1(n);
+
+ DynamicVector<K> b(m,1);
+
+ A.mv(b, res1);
+ A.umv(b, res2);
+
+ if( (res1 - res2).two_norm() > 1e-12 )
+ {
+ DUNE_THROW(FMatrixError,"mv and umv are not doing the same!");
+ }
+ }
+
+ {
+ FieldVector<K,m> v0;
+ for (size_t i=0; i<m; i++) v0[i] = v[i];
+ test_mult(A, v0, f );
+ }
+
+ {
+ DynamicVector<K> v0 ( v );
+ test_mult(A, v0, f );
+ }
+
+ {
+ std::vector<K> v1( m ) ;
+ std::vector<K> f1( n, 1 ) ;
+ // random access vector
+ for (size_type i=0; i<v1.size(); i++) v1[i] = i;
+ test_mult(A, v1, f1 );
+ }
+ {
+ K v2[ m ];
+ K f2[ n ];
+ // random access vector
+ for (size_type i=0; i<m; ++i) v2[i] = i;
+ for (size_type i=0; i<n; ++i) f2[i] = 1;
+ test_mult(A, v2, f2 );
+ }
+
+ // Test the different matrix norms
+ assert( A.frobenius_norm() >= 0 );
+ assert( A.frobenius_norm2() >= 0 );
+ assert( A.infinity_norm() >= 0 );
+ assert( A.infinity_norm_real() >= 0);
+
+ std::sort(v.begin(), v.end());
+
+ // print matrix
+ std::cout << A << std::endl;
+ // print vector
+ std::cout << f << std::endl;
+
+
+ {
+ DynamicMatrix<K> A2 = A;
+ A2 *= 2;
+
+ DynamicMatrix<K> B = A;
+ B += A;
+ B -= A2;
+ if (std::abs(B.infinity_norm()) > 1e-12)
+ DUNE_THROW(FMatrixError,"Operator +=/-= test failed!");
+ }
+ {
+ DynamicMatrix<K> A3 = A;
+ A3 *= 3;
+
+ DynamicMatrix<K> B = A;
+ B.axpy( K( 2 ), B );
+ B -= A3;
+ if (std::abs(B.infinity_norm()) > 1e-12)
+ DUNE_THROW(FMatrixError,"Axpy test failed!");
+ }
+ {
+ DynamicMatrix<K> A(n,n+1);
+ for(size_type i=0; i<A.N(); ++i)
+ for(size_type j=0; j<A.M(); ++j)
+ A[i][j] = i;
+ const DynamicMatrix<K>& Aref DUNE_UNUSED = A;
+
+
+ DynamicMatrix<K> B(n+1,n+1);
+ for(size_type i=0; i<B.N(); ++i)
+ for(size_type j=0; j<B.M(); ++j)
+ B[i][j] = i;
+ const DynamicMatrix<K>& Bref DUNE_UNUSED = B;
+
+ DynamicMatrix<K> C(n,n);
+ for(size_type i=0; i<C.N(); ++i)
+ for(size_type j=0; j<C.M(); ++j)
+ C[i][j] = i;
+ const DynamicMatrix<K>& Cref DUNE_UNUSED = C;
+
+#if 0
+ DynamicMatrix<K> AB = Aref.rightmultiplyany(B);
+ for(size_type i=0; i<AB.N(); ++i)
+ for(size_type j=0; j<AB.M(); ++j)
+ if (std::abs<double>(AB[i][j] - i*n*(n+1)/2) > 1e-10)
+ DUNE_THROW(FMatrixError,"Rightmultiplyany test failed!");
+
+ DynamicMatrix<K> AB2 = A;
+ AB2.rightmultiply(B);
+ AB2 -= AB;
+ if (std::abs(AB2.infinity_norm() > 1e-10))
+ DUNE_THROW(FMatrixError,"Rightmultiply test failed!");
+
+ DynamicMatrix<K> AB3 = Bref.leftmultiplyany(A);
+ AB3 -= AB;
+ if (std::abs(AB3.infinity_norm() > 1e-10))
+ DUNE_THROW(FMatrixError,"Leftmultiplyany test failed!");
+
+ DynamicMatrix<K> CA = Aref.leftmultiplyany(C);
+ for(size_type i=0; i<CA.N(); ++i)
+ for(size_type j=0; j<CA.M(); ++j)
+ if (std::abs<double>(CA[i][j] - i*n*(n-1)/2) > 1e-10)
+ DUNE_THROW(FMatrixError,"Leftmultiplyany test failed!");
+
+ DynamicMatrix<K> CA2 = A;
+ CA2.leftmultiply(C);
+ CA2 -= CA;
+ if (std::abs(CA2.infinity_norm() > 1e-10))
+ DUNE_THROW(FMatrixError,"Leftmultiply test failed!");
+
+ DynamicMatrix<K> CA3 = Cref.rightmultiplyany(A);
+ CA3 -= CA;
+ if (std::abs(CA3.infinity_norm() > 1e-10))
+ DUNE_THROW(FMatrixError,"Rightmultiplyany test failed!");
+#endif
+ }
+}
+
+int test_determinant()
+{
+ int ret = 0;
+
+ DynamicMatrix<double> B(4,4);
+ B[0][0] = 3.0; B[0][1] = 0.0; B[0][2] = 1.0; B[0][3] = 0.0;
+ B[1][0] = -1.0; B[1][1] = 3.0; B[1][2] = 0.0; B[1][3] = 0.0;
+ B[2][0] = -3.0; B[2][1] = 0.0; B[2][2] = -1.0; B[2][3] = 2.0;
+ B[3][0] = 0.0; B[3][1] = -1.0; B[3][2] = 0.0; B[3][3] = 1.0;
+ if (std::abs(B.determinant() + 2.0) > 1e-12)
+ {
+ std::cerr << "Determinant 1 test failed" << std::endl;
+ ++ret;
+ }
+
+ B[0][0] = 3.0; B[0][1] = 0.0; B[0][2] = 1.0; B[0][3] = 0.0;
+ B[1][0] = -1.0; B[1][1] = 3.0; B[1][2] = 0.0; B[1][3] = 0.0;
+ B[2][0] = -3.0; B[2][1] = 0.0; B[2][2] = -1.0; B[2][3] = 2.0;
+ B[3][0] = -1.0; B[3][1] = 3.0; B[3][2] = 0.0; B[3][3] = 2.0;
+ if (B.determinant() != 0.0)
+ {
+ std::cerr << "Determinant 2 test failed" << std::endl;
+ ++ret;
+ }
+
+ return 0;
+}
+
+int main()
+{
+ try {
+ Dune::DynamicMatrix<double> A( 5, 5 );
+ checkMatrixInterface( A );
+
+ test_matrix<float, 1, 1>();
+ test_matrix<double, 1, 1>();
+ test_matrix<int, 10, 5>();
+ test_matrix<double, 5, 10>();
+ test_determinant();
+ Dune::DynamicMatrix<double> B(34, 34, 1e-15);
+ for (int i=0; i<34; i++) B[i][i] = 1;
+ B.invert();
+ return test_invert_solve();
+ }
+ catch (Dune::Exception & e)
+ {
+ std::cerr << "Exception: " << e << std::endl;
+ }
+}
--- /dev/null
+// -*- 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 <dune/common/dynvector.hh>
+#include <dune/common/exceptions.hh>
+#include <iostream>
+
+using Dune::DynamicVector;
+
+template<class ct>
+void dynamicVectorTest(int d) {
+ ct a = 1;
+ DynamicVector<ct> v(d,1);
+ DynamicVector<ct> w(d,2);
+ DynamicVector<ct> z(d,2);
+ bool b DUNE_UNUSED;
+
+ // Test whether the norm methods compile
+ (w+v).two_norm();
+ (w+v).two_norm2();
+ (w+v).one_norm();
+ (w+v).one_norm_real();
+ (w+v).infinity_norm();
+ (w+v).infinity_norm_real();
+
+ // test op(vec,vec)
+ z = v + w;
+ z = v - w;
+ DynamicVector<ct> z2 = v + w;
+ w -= v;
+ w += v;
+
+ // test op(vec,scalar)
+ w +=a;
+ w -= a;
+ w *= a;
+ w /= a;
+
+ // test scalar product, axpy
+ a = v * w;
+ z = v.axpy(a,w);
+
+ // test comparison
+ b = (w != v);
+ b = (w == v);
+
+
+ // test istream operator
+ std::stringstream s;
+ for (int i=0; i<d; i++)
+ {
+ s << i << " ";
+ v[i] = i;
+ }
+ s >> w;
+ assert(v == w);
+
+}
+
+int main()
+{
+ try {
+ for (int d=1; d<6; d++)
+ {
+ dynamicVectorTest<int>(d);
+ dynamicVectorTest<float>(d);
+ dynamicVectorTest<double>(d);
+ }
+ } catch (Dune::Exception& e) {
+ std::cerr << e << std::endl;
+ return 1;
+ } catch (...) {
+ std::cerr << "Generic exception!" << std::endl;
+ return 2;
+ }
+}
--- /dev/null
+// -*- 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
+
+//==============================================================================
+//!
+//! \date Nov 9 2011
+//!
+//! \author Arne Morten Kvarving / SINTEF
+//!
+//==============================================================================
+
+#include <dune/common/fvector.hh>
+#include <dune/common/dynmatrixev.hh>
+
+#include <algorithm>
+#include <complex>
+
+
+//! \brief Represents a cardinal function on a line
+template<class ctype, class rtype>
+class LagrangeCardinalFunction
+{
+public:
+ //! \brief Empty default constructor
+ LagrangeCardinalFunction() {}
+
+ //! \brief Construct a cardinal function with the given nodes
+ //! \param[in] nodes_ The nodes
+ //! \param[in] i The node this function is associated with
+ LagrangeCardinalFunction(const std::vector<rtype>& nodes_,
+ size_t i)
+ : nodes(nodes_), node(i) {}
+
+ //! \brief Evaluate the shape function
+ //! \param[in] local The local coordinates
+ rtype evaluateFunction(const ctype& local) const
+ {
+ rtype result = 1;
+ for (size_t i=0; i < nodes.size(); ++i) {
+ if (i != node)
+ result *= (local-nodes[i])/(nodes[node]-nodes[i]);
+ }
+
+ return result;
+ }
+
+ //! \brief Evaluate the derivative of the cardinal function
+ //! \param[in] local The local coordinates
+ rtype evaluateGradient(const ctype& local) const
+ {
+ rtype result = 0;
+ for (size_t i=0; i < nodes.size(); ++i) {
+ rtype f = 1;
+ for (int j=0; j < nodes.size(); ++j) {
+ if (i != j && j != node)
+ f *= (local-nodes[j])/(nodes[node]-nodes[j]);
+ }
+ result += f/(nodes[node]-nodes[i]);
+ }
+
+ return result;
+ }
+
+private:
+ //! \brief The nodes
+ std::vector<rtype> nodes;
+
+ size_t node;
+};
+
+//! \brief Represents a tensor-product of 1D functions
+template<class rtype, class ctype, class ftype, int dim>
+class TensorProductFunction
+{
+public:
+ //! \brief The dimension of the function
+ enum { dimension = dim };
+
+ //! \brief Empty default constructor
+ TensorProductFunction() {}
+
+ //! \brief Construct a tensor-product function
+ //! \param[in] funcs_ The functions
+ TensorProductFunction(const Dune::FieldVector<ftype, dim>& funcs_)
+ : funcs(funcs_) {}
+
+ //! \brief Evaluate the function
+ //! \param[in] local The local coordinates
+ rtype evaluateFunction(const Dune::FieldVector<ctype,dim>& local) const
+ {
+ rtype result = 1;
+ for (int i=0; i < dim; ++i)
+ result *= funcs[i].evaluateFunction(local[i]);
+
+ return result;
+ }
+
+ Dune::FieldVector<rtype, dim>
+ evaluateGradient(const Dune::FieldVector<ctype,dim>& local) const
+ {
+ Dune::FieldVector<rtype, dim> result;
+ for (int i=0; i < dim; ++i)
+ result[i] = funcs[i].evaluateGradient(local[i]);
+ }
+private:
+ Dune::FieldVector<ftype, dim> funcs;
+};
+
+template<int dim>
+class PNShapeFunctionSet
+{
+public:
+ typedef LagrangeCardinalFunction<double, double> CardinalFunction;
+
+ typedef TensorProductFunction<double, double, CardinalFunction, dim>
+ ShapeFunction;
+
+ PNShapeFunctionSet(int n1, int n2, int n3=0)
+ {
+ int dims[3] = {n1, n2, n3};
+ cfuncs.resize(dim);
+ for (int i=0; i < dim; ++i) {
+ std::vector<double> grid;
+ grid = gaussLobattoLegendreGrid(dims[i]);
+ for (int j=0; j<dims[i]; ++j)
+ cfuncs[i].push_back(CardinalFunction(grid,j));
+ }
+ int l=0;
+ Dune::FieldVector<CardinalFunction,dim> fs;
+ if (dim == 3) {
+ f.resize(n1*n2*n3);
+ for (int k=0; k < n3; ++k) {
+ for (int j=0; j < n2; ++j)
+ for (int i=0; i< n1; ++i) {
+ fs[0] = cfuncs[0][i];
+ fs[1] = cfuncs[1][j];
+ fs[2] = cfuncs[2][k];
+ f[l++] = ShapeFunction(fs);
+ }
+ }
+ } else {
+ f.resize(n1*n2);
+ for (int j=0; j < n2; ++j) {
+ for (int i=0; i< n1; ++i) {
+ fs[0] = cfuncs[0][i];
+ fs[1] = cfuncs[1][j];
+ f[l++] = ShapeFunction(fs);
+ }
+ }
+ }
+ }
+
+ //! \brief Obtain a given shape function
+ //! \param[in] i The requested shape function
+ const ShapeFunction& operator[](int i) const
+ {
+ return f[i];
+ }
+
+ int size()
+ {
+ return f.size();
+ }
+protected:
+ std::vector< std::vector<CardinalFunction> > cfuncs;
+ std::vector<ShapeFunction> f;
+
+ double legendre(double x, int n)
+ {
+ std::vector<double> Ln;
+ Ln.resize(n+1);
+ Ln[0] = 1.f;
+ Ln[1] = x;
+ if( n > 1 ) {
+ for( int i=1; i<n; i++ )
+ Ln[i+1] = (2*i+1.0)/(i+1.0)*x*Ln[i]-i/(i+1.0)*Ln[i-1];
+ }
+
+ return Ln[n];
+ }
+
+ double legendreDerivative(double x, int n)
+ {
+ std::vector<double> Ln;
+ Ln.resize(n+1);
+
+ Ln[0] = 1.0; Ln[1] = x;
+
+ if( (x == 1.0) || (x == -1.0) )
+ return( pow(x,n-1)*n*(n+1.0)/2.0 );
+ else {
+ for( int i=1; i<n; i++ )
+ Ln[i+1] = (2.0*i+1.0)/(i+1.0)*x*Ln[i]-(double)i/(i+1.0)*Ln[i-1];
+ return( (double)n/(1.0-x*x)*Ln[n-1]-n*x/(1-x*x)*Ln[n] );
+ }
+ }
+
+
+ std::vector<double> gaussLegendreGrid(int n)
+ {
+ Dune::DynamicMatrix<double> A(n,n,0.0);
+
+ A[0][1] = 1.f;
+ for (int i=1; i<n-1; ++i) {
+ A[i][i-1] = (double)i/(2.0*(i+1.0)-1.0);
+ A[i][i+1] = (double)(i+1.0)/(2*(i+1.0)-1.0);
+ }
+ A[n-1][n-2] = (n-1.0)/(2.0*n-1.0);
+
+ Dune::DynamicVector<std::complex<double> > eigenValues(n);
+ Dune::DynamicMatrixHelp::eigenValuesNonSym(A, eigenValues);
+
+ std::vector<double> result(n);
+ for (int i=0; i < n; ++i)
+ result[i] = std::real(eigenValues[i]);
+ std::sort(result.begin(),result.begin()+n);
+
+ return result;
+ }
+
+ std::vector<double> gaussLobattoLegendreGrid(int n)
+ {
+ assert(n > 1);
+ const double tolerance = 1.e-15;
+
+ std::vector<double> result(n);
+ result[0] = 0.0;
+ result[n-1] = 1.0;
+ if (n == 3)
+ result[1] = 0.5;
+
+ if (n < 4)
+ return result;
+
+ std::vector<double> glgrid = gaussLegendreGrid(n-1);
+ for (int i=1; i<n-1; ++i) {
+ result[i] = (glgrid[i-1]+glgrid[i])/2.0;
+ double old = 0.0;
+ while (std::abs(old-result[i]) > tolerance) {
+ old = result[i];
+ double L = legendre(old, n-1);
+ double Ld = legendreDerivative(old, n-1);
+ result[i] += (1.0-old*old)*Ld/((n-1.0)*n*L);
+ }
+ result[i] = (result[i]+1.0)/2.0;
+ }
+
+ return result;
+ }
+};
+
+int main()
+{
+ // Not really a test but better than nothing.
+ PNShapeFunctionSet<2> lbasis(2, 3);
+ return 0;
+}
--- /dev/null
+// -*- 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 <dune/common/enumset.hh>
+#include <iostream>
+int main()
+{
+ using namespace Dune;
+ std::cout<<Combine<EnumItem<int,1>,EnumItem<int,2>,int>::contains(1)<<
+ " "<<Combine<EnumItem<int,1>,EnumItem<int,2>,int>::contains(2)<<
+ " "<<Combine<Combine<EnumItem<int,1>,EnumItem<int,2>,int>,EnumItem<int,0>,int>::contains(3)<<
+ " "<<EnumRange<int,1,3>::contains(3)<<std::endl;
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#include <config.h>
+
+#include <iostream>
+#include <dune/common/fvector.hh>
+#include <dune/common/fassign.hh>
+
+using namespace Dune;
+
+int main(int, char**) try
+{
+ Dune::FieldVector<double,3> pos;
+
+ pos <<= 1, 0, 0;
+
+}
+catch (Exception e) {
+
+ std::cout << e << std::endl;
+
+}
--- /dev/null
+// -*- 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
+// Activate checking.
+#ifndef DUNE_ISTL_WITH_CHECKING
+#define DUNE_ISTL_WITH_CHECKING
+#endif
+#include <dune/common/fmatrix.hh>
+#include <dune/common/fassign.hh>
+#include <dune/common/classname.hh>
+#include <iostream>
+#include <algorithm>
+#include <vector>
+#include <cassert>
+#include <complex>
+
+#include "checkmatrixinterface.hh"
+
+using namespace Dune;
+
+template<typename T, std::size_t n>
+int test_invert_solve(T A_data[n*n], T inv_data[n*n],
+ T x_data[n], T b_data[n])
+{
+ int ret=0;
+
+ std::cout <<"Checking inversion of:"<<std::endl;
+
+ FieldMatrix<T,n,n> A, inv, calced_inv;
+ FieldVector<T,n> x, b, calced_x;
+
+ for(size_t i =0; i < n; ++i) {
+ x[i]=x_data[i];
+ b[i]=b_data[i];
+ for(size_t j=0; j <n; ++j) {
+ A[i][j] = A_data[i*n+j];
+ inv[i][j] = inv_data[i*n+j];
+ }
+ }
+
+ std::cout<<A<<std::endl;
+
+ // Check whether given inverse is correct
+ FieldMatrix<T,n,n> prod = A;
+ prod.rightmultiply(inv);
+ for (size_t i=0; i<n; i++)
+ prod[i][i] -= 1;
+
+ bool equal=true;
+ if (prod.infinity_norm() > 1e-6) {
+ std::cerr<<"Given inverse wrong"<<std::endl;
+ equal=false;
+ }
+
+ FieldMatrix<T,n,n> copy(A);
+ A.invert();
+
+ calced_inv = A;
+ A-=inv;
+
+
+ double singthres = FMatrixPrecision<>::singular_limit()*10;
+ for(size_t i =0; i < n; ++i)
+ for(size_t j=0; j <n; ++j)
+ if(std::abs(A[i][j])>singthres) {
+ std::cerr<<"calculated inverse wrong at ("<<i<<","<<j<<")"<<std::endl;
+ equal=false;
+ }
+
+ if(!equal) {
+ ret++;
+ std::cerr<<"Calculated inverse was:"<<std::endl;
+ std::cerr <<calced_inv<<std::endl;
+ std::cerr<<"Should have been"<<std::endl;
+ std::cerr<<inv << std::endl;
+ }else
+ std::cout<<"Result is"<<std::endl<<calced_inv<<std::endl;
+
+
+ std::cout<<"Checking solution for rhs="<<b<<std::endl;
+
+ // Check whether given solution is correct
+ FieldVector<T,n> trhs=b;
+
+ copy.mmv(x,trhs);
+ equal=true;
+
+ if (trhs.infinity_norm() > 1e-6) {
+ std::cerr<<"Given rhs does not fit solution"<<std::endl;
+ equal=false;
+ }
+ copy.solve(calced_x, b);
+ FieldVector<T,n> xcopy(calced_x);
+ xcopy-=x;
+
+ equal=true;
+
+ for(size_t i =0; i < n; ++i)
+ if(std::abs(xcopy[i])>singthres) {
+ std::cerr<<"calculated isolution wrong at ("<<i<<")"<<std::endl;
+ equal=false;
+ }
+
+ if(!equal) {
+ ret++;
+ std::cerr<<"Calculated solution was:"<<std::endl;
+ std::cerr <<calced_x<<std::endl;
+ std::cerr<<"Should have been"<<std::endl;
+ std::cerr<<x<<std::endl;
+ std::cerr<<"difference is "<<xcopy<<std::endl;
+ }else
+ std::cout<<"Result is "<<calced_x<<std::endl;
+
+ return ret;
+}
+
+
+int test_invert_solve()
+{
+ int ret=0;
+
+ double A_data[9] = {1, 5, 7, 2, 14, 15, 4, 40, 39};
+ double inv_data[9] = {-9.0/4, 85.0/24, -23.0/24, -3.0/4, 11.0/24, -1.0/24, 1, -5.0/6, 1.0/6};
+ double b[3] = {32,75,201};
+ double x[3] = {1,2,3};
+
+ ret += test_invert_solve<double,3>(A_data, inv_data, x, b);
+
+ double A_data0[9] = {-0.5, 0, -0.25, 0.5, 0, -0.25, 0, 0.5, 0};
+ double inv_data0[9] = {-1, 1, 0, 0, 0, 2, -2, -2, 0};
+ double b0[3] = {32,75,201};
+ double x0[3] = {43, 402, -214};
+
+ ret += test_invert_solve<double,3>(A_data0, inv_data0, x0, b0);
+
+ double A_data1[9] = {0, 1, 0, 1, 0, 0, 0, 0, 1};
+ double b1[3] = {0,1,2};
+ double x1[3] = {1,0,2};
+
+ ret += test_invert_solve<double,3>(A_data1, A_data1, x1, b1);
+
+ double A_data2[9] ={3, 1, 6, 2, 1, 3, 1, 1, 1};
+ double inv_data2[9] ={-2, 5, -3, 1, -3, 3, 1, -2, 1};
+ double b2[3] = {2, 7, 4};
+ double x2[3] = {19,-7,-8};
+
+ return ret + test_invert_solve<double,3>(A_data2, inv_data2, x2, b2);
+}
+
+template<class K, int n, int m, class X, class Y>
+void test_mult(FieldMatrix<K, n, m>& A,
+ X& v, Y& f)
+{
+ // test the various matrix-vector products
+ A.mv(v,f);
+ A.mtv(f,v);
+ A.umv(v,f);
+ A.umtv(f,v);
+ A.umhv(f,v);
+ A.mmv(v,f);
+ A.mmtv(f,v);
+ A.mmhv(f,v);
+ A.usmv(0.5,v,f);
+ A.usmtv(0.5,f,v);
+ A.usmhv(0.5,f,v);
+}
+
+
+template<class K, int n, int m>
+void test_matrix()
+{
+ typedef typename FieldMatrix<K,n,m>::size_type size_type;
+
+ FieldMatrix<K,n,m> A;
+ FieldVector<K,n> f;
+ FieldVector<K,m> v;
+
+ // assign matrix
+ A=K();
+ // random access matrix
+ for (size_type i=0; i<n; i++)
+ for (size_type j=0; j<m; j++)
+ A[i][j] = i*j;
+ // iterator matrix
+ typename FieldMatrix<K,n,m>::RowIterator rit = A.begin();
+ for (; rit!=A.end(); ++rit)
+ {
+ rit.index();
+ typename FieldMatrix<K,n,m>::ColIterator cit = rit->begin();
+ for (; cit!=rit->end(); ++cit)
+ {
+ cit.index();
+ (*cit) *= 2;
+ }
+ }
+
+ // assign vector
+ f = 1;
+
+ // random access vector
+ for (size_type i=0; i<v.dim(); i++)
+ v[i] = i;
+ // iterator vector
+ typename FieldVector<K,m>::iterator it = v.begin();
+ typename FieldVector<K,m>::ConstIterator end = v.end();
+ for (; it!=end; ++it)
+ {
+ it.index();
+ (*it) *= 2;
+ }
+ // reverse iterator vector
+ it = v.beforeEnd();
+ end = v.beforeBegin();
+ for (; it!=end; --it)
+ (*it) /= 2;
+ // find vector
+ for (size_type i=0; i<v.dim(); i++)
+ {
+ it = v.find(i);
+ (*it) += 1;
+ }
+
+ // matrix vector product
+ A.umv(v,f);
+ // check that mv and umv are doing the same thing
+ {
+ FieldVector<K,n> res2(0);
+ FieldVector<K,n> res1;
+
+ FieldVector<K,m> b(1);
+
+ A.mv(b, res1);
+ A.umv(b, res2);
+
+ if( (res1 - res2).two_norm() > 1e-12 )
+ {
+ DUNE_THROW(FMatrixError,"mv and umv are not doing the same!");
+ }
+ }
+
+ {
+ FieldVector<K,m> v0 ( v );
+ test_mult(A, v0, f );
+ }
+
+ {
+ std::vector<K> v1( m ) ;
+ std::vector<K> f1( n, 1 ) ;
+ // random access vector
+ for (size_type i=0; i<v1.size(); i++) v1[i] = i;
+ test_mult(A, v1, f1 );
+ }
+ {
+ K v2[ m ];
+ K f2[ n ];
+ // random access vector
+ for (size_type i=0; i<m; ++i) v2[i] = i;
+ for (size_type i=0; i<n; ++i) f2[i] = 1;
+ test_mult(A, v2, f2 );
+ }
+
+ // Test the different matrix norms
+ assert( A.frobenius_norm() >= 0 );
+ assert( A.frobenius_norm2() >= 0 );
+ assert( A.infinity_norm() >= 0 );
+ assert( A.infinity_norm_real() >= 0);
+
+ // print matrix
+ std::cout << A << std::endl;
+ // print vector
+ std::cout << f << std::endl;
+
+
+ {
+ FieldMatrix<K,n,m> A2 = A;
+ A2 *= 2;
+
+ FieldMatrix<K,n,m> B = A;
+ B += A;
+ B -= A2;
+ if (std::abs(B.infinity_norm()) > 1e-12)
+ DUNE_THROW(FMatrixError,"Operator +=/-= test failed!");
+ }
+ {
+ FieldMatrix<K,n,m> A3 = A;
+ A3 *= 3;
+
+ FieldMatrix<K,n,m> B = A;
+ B.axpy( K( 2 ), B );
+ B -= A3;
+ if (std::abs(B.infinity_norm()) > 1e-12)
+ DUNE_THROW(FMatrixError,"Axpy test failed!");
+ }
+ {
+ FieldMatrix<K,n,n+1> A;
+ for(size_type i=0; i<A.N(); ++i)
+ for(size_type j=0; j<A.M(); ++j)
+ A[i][j] = i;
+ const FieldMatrix<K,n,n+1>& Aref = A;
+
+
+ FieldMatrix<K,n+1,n+1> B;
+ for(size_type i=0; i<B.N(); ++i)
+ for(size_type j=0; j<B.M(); ++j)
+ B[i][j] = i;
+ const FieldMatrix<K,n+1,n+1>& Bref = B;
+
+ FieldMatrix<K,n,n> C;
+ for(size_type i=0; i<C.N(); ++i)
+ for(size_type j=0; j<C.M(); ++j)
+ C[i][j] = i;
+ const FieldMatrix<K,n,n>& Cref = C;
+
+ FieldMatrix<K,n,n+1> AB = Aref.rightmultiplyany(B);
+ for(size_type i=0; i<AB.N(); ++i)
+ for(size_type j=0; j<AB.M(); ++j)
+ if (std::abs(AB[i][j] - K(i*n*(n+1)/2)) > 1e-10)
+ DUNE_THROW(FMatrixError,"Rightmultiplyany test failed!");
+
+ FieldMatrix<K,n,n+1> AB2 = A;
+ AB2.rightmultiply(B);
+ AB2 -= AB;
+ if (std::abs(AB2.infinity_norm()) > 1e-10)
+ DUNE_THROW(FMatrixError,"Rightmultiply test failed!");
+
+ FieldMatrix<K,n,n+1> AB3 = Bref.leftmultiplyany(A);
+ AB3 -= AB;
+ if (std::abs(AB3.infinity_norm() > 1e-10))
+ DUNE_THROW(FMatrixError,"Leftmultiplyany test failed!");
+
+ FieldMatrix<K,n,n+1> CA = Aref.leftmultiplyany(C);
+ for(size_type i=0; i<CA.N(); ++i)
+ for(size_type j=0; j<CA.M(); ++j)
+ if (std::abs(CA[i][j] - K(i*n*(n-1)/2)) > 1e-10)
+ DUNE_THROW(FMatrixError,"Leftmultiplyany test failed!");
+
+ FieldMatrix<K,n,n+1> CA2 = A;
+ CA2.leftmultiply(C);
+ CA2 -= CA;
+ if (std::abs(CA2.infinity_norm()) > 1e-10)
+ DUNE_THROW(FMatrixError,"Leftmultiply test failed!");
+
+ FieldMatrix<K,n,n+1> CA3 = Cref.rightmultiplyany(A);
+ CA3 -= CA;
+ if (std::abs(CA3.infinity_norm()) > 1e-10)
+ DUNE_THROW(FMatrixError,"Rightmultiplyany test failed!");
+ }
+}
+
+int test_determinant()
+{
+ int ret = 0;
+
+ FieldMatrix<double, 4, 4> B;
+ B[0][0] = 3.0; B[0][1] = 0.0; B[0][2] = 1.0; B[0][3] = 0.0;
+ B[1][0] = -1.0; B[1][1] = 3.0; B[1][2] = 0.0; B[1][3] = 0.0;
+ B[2][0] = -3.0; B[2][1] = 0.0; B[2][2] = -1.0; B[2][3] = 2.0;
+ B[3][0] = 0.0; B[3][1] = -1.0; B[3][2] = 0.0; B[3][3] = 1.0;
+ if (std::abs(B.determinant() + 2.0) > 1e-12)
+ {
+ std::cerr << "Determinant 1 test failed" << std::endl;
+ ++ret;
+ }
+
+ B[0][0] = 3.0; B[0][1] = 0.0; B[0][2] = 1.0; B[0][3] = 0.0;
+ B[1][0] = -1.0; B[1][1] = 3.0; B[1][2] = 0.0; B[1][3] = 0.0;
+ B[2][0] = -3.0; B[2][1] = 0.0; B[2][2] = -1.0; B[2][3] = 2.0;
+ B[3][0] = -1.0; B[3][1] = 3.0; B[3][2] = 0.0; B[3][3] = 2.0;
+ if (B.determinant() != 0.0)
+ {
+ std::cerr << "Determinant 2 test failed" << std::endl;
+ ++ret;
+ }
+
+ return 0;
+}
+
+template<class ft>
+struct ScalarOperatorTest
+{
+ ScalarOperatorTest()
+ {
+ ft a = 1;
+ ft c = 2;
+ FieldMatrix<ft,1,1> v(2);
+ FieldMatrix<ft,1,1> w(2);
+ bool b DUNE_UNUSED;
+
+ std::cout << __func__ << "\t ( " << className(v) << " )" << std::endl;
+
+ a = a * c;
+ a = a + c;
+ a = a / c;
+ a = a - c;
+
+ v = a;
+ v = w = v;
+ a = v;
+
+ a = v + a;
+ a = v - a;
+ a = v * a;
+ a = v / a;
+
+ v = v + a;
+ v = v - a;
+ v = v * a;
+ v = v / a;
+
+ a = a + v;
+ a = a - v;
+ a = a * v;
+ a = a / v;
+
+ v = a + v;
+ v = a - v;
+ v = a * v;
+ v = a / v;
+
+ v -= v;
+ v -= a;
+ v += v;
+ v += a;
+ v *= a;
+ v /= a;
+
+ b = (v == a);
+ b = (v != a);
+ b = (a == v);
+ b = (a != v);
+
+ }
+};
+
+template<typename ft>
+void test_ev()
+{
+ // rosser test matrix
+
+ /*
+ This matrix was a challenge for many matrix eigenvalue
+ algorithms. But the Francis QR algorithm, as perfected by
+ Wilkinson and implemented in EISPACK, has no trouble with it. The
+ matrix is 8-by-8 with integer elements. It has:
+
+ * A double eigenvalue
+ * Three nearly equal eigenvalues
+ * Dominant eigenvalues of opposite sign
+ * A zero eigenvalue
+ * A small, nonzero eigenvalue
+
+ */
+ Dune::FieldMatrix<ft,8,8> A;
+ A <<=
+ 611, 196, -192, 407, -8, -52, -49, 29, Dune::nextRow,
+ 196, 899, 113, -192, -71, -43, -8, -44, Dune::nextRow,
+ -192, 113, 899, 196, 61, 49, 8, 52, Dune::nextRow,
+ 407, -192, 196, 611, 8, 44, 59, -23, Dune::nextRow,
+ -8, -71, 61, 8, 411, -599, 208, 208, Dune::nextRow,
+ -52, -43, 49, 44, -599, 411, 208, 208, Dune::nextRow,
+ -49, -8, 8, 59, 208, 208, 99, -911, Dune::nextRow,
+ 29, -44, 52, -23, 208, 208, -911, 99;
+
+ // compute eigenvalues
+ Dune::FieldVector<ft,8> eig;
+ Dune::FMatrixHelp::eigenValues(A, eig);
+
+ // test results
+ Dune::FieldVector<ft,8> ref;
+ /*
+ reference solution computed with octave 3.2
+
+ > format long e
+ > eig(rosser())
+
+ */
+ ref <<=
+ -1.02004901843000e+03,
+ -4.14362871168386e-14,
+ 9.80486407214362e-02,
+ 1.00000000000000e+03,
+ 1.00000000000000e+03,
+ 1.01990195135928e+03,
+ 1.02000000000000e+03,
+ 1.02004901843000e+03;
+
+ if( (ref - eig).two_norm() > 1e-10 )
+ {
+ DUNE_THROW(FMatrixError,"error computing eigenvalues");
+ }
+
+ std::cout << "Eigenvalues of Rosser matrix: " << eig << std::endl;
+}
+
+template< class K, int n >
+void test_invert ()
+{
+ Dune::FieldMatrix< K, n, n > A( 1e-15 );
+ for( int i = 0; i < n; ++i )
+ A[ i ][ i ] = K( 1 );
+ A.invert();
+}
+
+// Make sure that a matrix with only NaN entries has norm NaN.
+// Prior to r6819, the infinity_norm would be zero; see also FS #1147.
+void
+test_nan()
+{
+ double mynan = 0.0/0.0;
+
+ Dune::FieldMatrix<double, 2, 2> m2(mynan);
+ assert(std::isnan(m2.infinity_norm()));
+ assert(std::isnan(m2.frobenius_norm()));
+ assert(std::isnan(m2.frobenius_norm2()));
+
+ Dune::FieldMatrix<double, 0, 2> m02(mynan);
+ assert(0.0 == m02.infinity_norm());
+ assert(0.0 == m02.frobenius_norm());
+ assert(0.0 == m02.frobenius_norm2());
+
+ Dune::FieldMatrix<double, 2, 0> m20(mynan);
+ assert(0.0 == m20.infinity_norm());
+ assert(0.0 == m20.frobenius_norm());
+ assert(0.0 == m20.frobenius_norm2());
+}
+
+// The computation of infinity_norm_real() was flawed from r6819 on
+// until r6915.
+void
+test_infinity_norms()
+{
+ std::complex<double> threefour(3.0, -4.0);
+ std::complex<double> eightsix(8.0, -6.0);
+
+ Dune::FieldMatrix<std::complex<double>, 2, 2> m;
+ m[0] = threefour;
+ m[1] = eightsix;
+ assert(std::abs(m.infinity_norm() -20.0) < 1e-10); // max(5+5, 10+10)
+ assert(std::abs(m.infinity_norm_real()-28.0) < 1e-10); // max(7+7, 14+14)
+}
+
+
+template< class K, int rows, int cols >
+void test_interface()
+{
+ typedef CheckMatrixInterface::UseFieldVector< K, rows, cols > Traits;
+ typedef Dune::FieldMatrix< K, rows, cols > FMatrix;
+
+ FMatrix m( 1 );
+ checkMatrixInterface< FMatrix >( m );
+ checkMatrixInterface< FMatrix, Traits >( m );
+}
+
+int main()
+{
+ try {
+ test_nan();
+ test_infinity_norms();
+
+ // test 1 x 1 matrices
+ test_interface<float, 1, 1>();
+ test_matrix<float, 1, 1>();
+ ScalarOperatorTest<float>();
+ test_matrix<double, 1, 1>();
+ ScalarOperatorTest<double>();
+ // test n x m matrices
+ test_interface<int, 10, 5>();
+ test_matrix<int, 10, 5>();
+ test_matrix<double, 5, 10>();
+ test_interface<double, 5, 10>();
+ // test complex matrices
+ test_matrix<std::complex<float>, 1, 1>();
+ test_matrix<std::complex<double>, 5, 10>();
+#if HAVE_LAPACK
+ // test eigemvalue computation
+ test_ev<double>();
+#endif
+ // test high level methods
+ test_determinant();
+ test_invert< float, 34 >();
+ test_invert< double, 34 >();
+ test_invert< std::complex< long double >, 2 >();
+ return test_invert_solve();
+ }
+ catch (Dune::Exception & e)
+ {
+ std::cerr << "Exception: " << e << std::endl;
+ }
+}
--- /dev/null
+// -*- 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 <dune/common/fvector.hh>
+#include <dune/common/exceptions.hh>
+#include <dune/common/typetraits.hh>
+#include <dune/common/static_assert.hh>
+#include <dune/common/classname.hh>
+#include <iostream>
+#include <complex>
+#include <typeinfo>
+#include <cassert>
+
+
+using Dune::FieldVector;
+using std::complex;
+
+template<class ft, class rt, int d>
+struct FieldVectorMainTest
+{
+ FieldVectorMainTest() {
+ ft a = 1;
+ FieldVector<ft,d> v(1);
+ FieldVector<ft,d> w(2);
+ FieldVector<ft,d> z(2);
+ const FieldVector<ft,d> x(z);
+ if (x.size()>0)
+ a = x[0];
+ bool b DUNE_UNUSED;
+ rt n DUNE_UNUSED;
+
+ std::cout << __func__ << "\t ( " << className(v) << " )" << std::endl;
+
+ // test traits
+ dune_static_assert(
+ ( Dune::is_same< typename Dune::FieldTraits<
+ FieldVector<ft,d> >::field_type, ft >::value ),
+ "FieldTraits<FieldVector> yields wrong field_type"
+ );
+ dune_static_assert(
+ ( Dune::is_same< typename Dune::FieldTraits<ft>::real_type, rt >::value ),
+ "FieldTraits<field_type> yields wrong real_type"
+ );
+ dune_static_assert(
+ ( Dune::is_same< typename Dune::FieldTraits<
+ FieldVector<ft,d> >::real_type, rt >::value ),
+ "FieldTraits<FieldVector> yields wrong real_type"
+ );
+
+ // Test whether the norm methods compile
+ n = (w+v).two_norm();
+ n = (w+v).two_norm2();
+ n = (w+v).one_norm();
+ n = (w+v).one_norm_real();
+ n = (w+v).infinity_norm();
+ n = (w+v).infinity_norm_real();
+
+ // test op(vec,vec)
+ z = v + w;
+ z = v - w;
+ FieldVector<ft,d> z2 DUNE_UNUSED = v + w;
+ w -= v;
+ w += v;
+
+ // test op(vec,scalar)
+ w +=a;
+ w -= a;
+ w *= a;
+ w /= a;
+
+ // test scalar product, axpy
+ a = v * w;
+ a = v.dot(w);
+ z = v.axpy(a,w);
+
+ // test comparison
+ b = (w != v);
+ b = (w == v);
+
+ // assignment to vector of complex
+ FieldVector< std::complex<rt> ,d> cv = v;
+ cv = a;
+ const FieldVector< std::complex<rt> ,d> ccv DUNE_UNUSED = x;
+
+ // test istream operator
+ std::stringstream s;
+ for (int i=0; i<d; i++)
+ {
+ s << i << " ";
+ v[i] = i;
+ }
+ s >> w;
+ assert(v == w);
+
+ // test container methods
+ typename FieldVector<ft,d>::size_type size = FieldVector<ft,d>::dimension;
+ assert(size == w.size());
+ }
+};
+
+
+template<class ft>
+struct ScalarOperatorTest
+{
+ ScalarOperatorTest()
+ {
+ ft a = 1;
+ ft c = 2;
+ FieldVector<ft,1> v(2);
+ FieldVector<ft,1> w(2);
+ bool b DUNE_UNUSED;
+
+ std::cout << __func__ << "\t ( " << className(v) << " )" << std::endl;
+
+ a = a * c;
+ a = a + c;
+ a = a / c;
+ a = a - c;
+
+ v = a;
+ v = w = v;
+ a = v;
+
+ a = v + a;
+ a = v - a;
+ a = v * a;
+ a += (ft)1; // make sure a!=0
+ a = v / a;
+
+ v = v + a;
+ v = v - a;
+ v = v * a;
+ a += (ft)1; // make sure a!=0
+ v = v / a;
+
+ a = a + v;
+ a = a - v;
+ a = a * v;
+ v += (ft)1; // make sure v!=0
+ a = a / v;
+
+ v = a + v;
+ v = a - v;
+ v = a * v;
+ v += (ft)1; // make sure v!=0
+ v = a / v;
+
+ v -= v;
+ v -= a;
+ v += v;
+ v += a;
+ v *= a;
+ a += (ft)1; // make sure a!=0
+ v /= a;
+
+ b = (v == a);
+ b = (v != a);
+ b = (a == v);
+ b = (a != v);
+
+ }
+};
+
+// scalar ordering doesn't work for complex numbers
+template<class ft>
+struct ScalarOrderingTest
+{
+ ScalarOrderingTest()
+ {
+ ft a = 1;
+ ft c = 2;
+ FieldVector<ft,1> v(2);
+ FieldVector<ft,1> w(2);
+ bool b DUNE_UNUSED;
+
+ std::cout << __func__ << "\t ( " << className(v) << " )" << std::endl;
+
+ b = (a < c);
+ b = (a <= c);
+ b = (a >= c);
+ b = (a > c);
+
+ b = (v == a);
+ b = (v != a);
+ b = (a == v);
+ b = (a != v);
+
+ b = (v < a);
+ b = (v <= a);
+ b = (v >= a);
+ b = (v > a);
+
+ b = (v < w);
+ b = (v <= w);
+ b = (v >= w);
+ b = (v > w);
+
+ b = (a < w);
+ b = (a <= w);
+ b = (a >= w);
+ b = (a > w);
+ }
+};
+
+// scalar ordering doesn't work for complex numbers
+template <class rt, int d>
+struct DotProductTest
+{
+ DotProductTest() {
+ typedef std::complex<rt> ct;
+ const rt myEps(1e-6);
+
+ dune_static_assert(
+ ( Dune::is_same< typename Dune::FieldTraits<rt>::real_type, rt>::value ),
+ "DotProductTest requires real data type as template parameter!"
+ );
+
+ const ct I(0.,1.); // imaginary unit
+ const FieldVector<rt,d> one(1.); // vector filled with 1
+ const FieldVector<ct,d> iVec(ct(0.,1.)); // vector filled with I
+
+ std::cout << __func__ << "\t \t ( " << Dune::className(one) << " and " << Dune::className(iVec) << ")" << std::endl;
+
+ const bool isRealOne = Dune::is_same<typename Dune::FieldTraits<rt>::field_type,typename Dune::FieldTraits<rt>::real_type>::value;
+ const bool isRealIVec = Dune::is_same<typename Dune::FieldTraits<ct>::field_type,typename Dune::FieldTraits<ct>::real_type> ::value;
+ dune_static_assert(isRealOne,"1-vector expected to be real");
+ dune_static_assert(!isRealIVec,"i-vector expected to be complex");
+
+ ct result = ct();
+ ct length = ct(d);
+
+
+ // one^H*one should equal d
+ result = dot(one,one);
+ assert(std::abs(result-length)<= myEps);
+ result = one.dot(one);
+ assert(std::abs(result-length)<= myEps);
+
+
+ // iVec^H*iVec should equal d
+ result = dot(iVec,iVec);
+ assert(std::abs(result-length)<= myEps);
+ result = iVec.dot(iVec);
+ assert(std::abs(result-length)<= myEps);
+
+
+ // test that we do conjugate first argument
+ result = dot(one,iVec);
+ assert(std::abs(result-length*I)<= myEps);
+ result = dot(one,iVec);
+ assert(std::abs(result-length*I)<= myEps);
+
+
+ // test that we do not conjugate second argument
+ result = dot(iVec,one);
+ assert(std::abs(result+length*I)<= myEps);
+ result = iVec.dot(one);
+ assert(std::abs(result+length*I)<= myEps);
+
+
+ // test that dotT does not conjugate at all
+ result = dotT(one,one) + one*one;
+ assert(std::abs(result-ct(2)*length)<= myEps);
+ result = dotT(iVec,iVec) + iVec*iVec;
+ assert(std::abs(result+ct(2)*length)<= myEps);
+ result = dotT(one,iVec) + one*iVec;
+ assert(std::abs(result-ct(2)*length*I)<= myEps);
+ result = dotT(iVec,one) + iVec*one;
+ assert(std::abs(result-ct(2)*length*I)<= myEps);
+
+ }
+
+};
+
+template<class ft, int d>
+struct FieldVectorTest
+{
+ FieldVectorTest()
+ {
+ // --- test complex and real valued vectors
+ FieldVectorMainTest<ft,ft,d>();
+ FieldVectorMainTest<complex<ft>,ft,d>();
+ DotProductTest<ft,d>();
+ // --- test next lower dimension
+ FieldVectorTest<ft,d-1>();
+ }
+};
+
+// specialization for 1d vector
+template<class ft>
+class FieldVectorTest<ft,1>
+{
+public:
+ FieldVectorTest()
+ {
+ // --- real valued
+ FieldVectorMainTest<ft,ft,1>();
+ ScalarOperatorTest<ft>();
+ ScalarOrderingTest<ft>();
+ DotProductTest<ft,1>();
+ // --- complex valued
+ FieldVectorMainTest<complex<ft>,ft,1>();
+ ScalarOperatorTest< complex<ft> >();
+ // ordering doesn't work for complex numbers
+
+ // --- test next lower dimension
+ FieldVectorMainTest<ft,ft,0>();
+ }
+};
+
+// Make sure that a vector with only NaN entries has norm NaN.
+// Prior to r6914, the infinity_norm would be zero; see also FS #1147.
+void
+test_nan()
+{
+ double mynan = 0.0/0.0;
+
+ Dune::FieldVector<double, 2> v2(mynan);
+ assert(std::isnan(v2.infinity_norm()));
+ assert(std::isnan(v2.one_norm()));
+ assert(std::isnan(v2.two_norm()));
+ assert(std::isnan(v2.two_norm2()));
+
+ Dune::FieldVector<double, 0> v0(mynan);
+ assert(0.0 == v0.infinity_norm());
+ assert(0.0 == v0.one_norm());
+ assert(0.0 == v0.two_norm());
+ assert(0.0 == v0.two_norm2());
+}
+
+void
+test_infinity_norms()
+{
+ std::complex<double> threefour(3.0, -4.0);
+ std::complex<double> eightsix(8.0, -6.0);
+
+ Dune::FieldVector<std::complex<double>, 2> v;
+ v[0] = threefour;
+ v[1] = eightsix;
+ assert(std::abs(v.infinity_norm() -10.0) < 1e-10); // max(5,10)
+ assert(std::abs(v.infinity_norm_real()-14.0) < 1e-10); // max(7,14)
+}
+
+int main()
+{
+ try {
+ FieldVectorTest<int, 3>();
+ FieldVectorTest<float, 3>();
+ FieldVectorTest<double, 3>();
+
+ test_nan();
+ test_infinity_norms();
+ } catch (Dune::Exception& e) {
+ std::cerr << e << std::endl;
+ return 1;
+ } catch (...) {
+ std::cerr << "Generic exception!" << std::endl;
+ return 2;
+ }
+}
--- /dev/null
+// -*- 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/gcd.hh>
+#include <dune/common/lcm.hh>
+#include <dune/common/static_assert.hh>
+
+void test()
+{
+ dune_static_assert((Dune::Gcd<2*2*2*5*5*5*11, 2*2*5*13>::value == 2*2*5), "gcd not working properly");
+ dune_static_assert((Dune::Lcm<11,3>::value == 33), "lcm not working properly");
+ dune_static_assert((Dune::Lcm<18,15>::value == 18*15/3), "lcm not working properly");
+ dune_static_assert((Dune::Lcm<10800,Dune::Lcm<36000,7680>::value>::value==1728000), "lcm not working properly");
+}
+
+int main()
+{
+ std::cout<<" gcd(2,5)="<<Dune::Gcd<2,5>::value<<" gcd(3, 18)="
+ <<Dune::Gcd<3,18>::value<<" gcd("<<2*2*2*5*5*5*11<<", "
+ << 2*2*5*13<<")="<<Dune::Gcd<2*2*2*5*5*5*11, 2*2*5*13>::value
+ <<std::endl;
+ std::cout<<" lcm(18,15)="<<Dune::Lcm<18,15>::value
+ <<" lcm(10800,36000,7680)="<<Dune::Lcm<10800,Dune::Lcm<36000,7680>::value>::value<<std::endl;
+
+}
--- /dev/null
+// -*- 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 <dune/common/test/iteratorfacadetest.hh>
+#include <dune/common/test/iteratortest.hh>
+
+int main(){
+ // Test the TestIterator;
+ typedef TestContainer<double, Dune::BidirectionalIteratorFacade> Container;
+ Container bidicontainer;
+
+ Container::const_iterator cit = bidicontainer.begin();
+ //This should fail since makeing a mutable iterator from a const iterator
+ //discard qualifiers
+ Container::iterator it DUNE_UNUSED;
+ it = cit;
+}
--- /dev/null
+// -*- 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 <dune/common/test/iteratorfacadetest.hh>
+#include <dune/common/test/iteratortest.hh>
+#include <iostream>
+#include <algorithm>
+
+template<class Container>
+void randomize(Container& cont){
+ srand(300);
+ double size=1000;
+
+ for(int i=0; i < 100; i++) {
+ cont[i] = (size*(rand()/(RAND_MAX+1.0)));
+
+ }
+}
+
+template<class Container>
+void print(Container& cont){
+ for(int i=0; i < 100; i++)
+ std::cout<<cont[i]<<" ";
+ std::cout<<std::endl;
+}
+
+template<class Container>
+int containerTest(Container & container)
+{
+ randomize(container);
+ // print(container);
+ //std::sort(container.begin(), container.end());
+ //print(container);
+
+ const Container ccontainer(container);
+ int ret=0;
+ Printer<const double> print;
+ ret += testIterator(container, print);
+ ret += testIterator(ccontainer, print);
+
+ return ret;
+}
+
+int main(){
+ // Test the TestIterator;
+ TestContainer<double, Dune::ForwardIteratorFacade> forwardcontainer;
+ TestContainer<double, Dune::BidirectionalIteratorFacade> bidicontainer;
+ TestContainer<double, Dune::RandomAccessIteratorFacade> randomcontainer;
+
+ int ret=0;
+
+ ret += containerTest(forwardcontainer);
+ ret += containerTest(bidicontainer);
+ ret += containerTest(randomcontainer);
+
+ return (ret);
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_ITERATORFACADETEST_HH
+#define DUNE_ITERATORFACADETEST_HH
+#include <dune/common/iteratorfacades.hh>
+#include <dune/common/genericiterator.hh>
+#include <dune/common/typetraits.hh>
+
+template<class T,
+ template<class,class,class,class> class IteratorFacade=Dune::RandomAccessIteratorFacade>
+class TestContainer {
+public:
+ typedef Dune::GenericIterator<TestContainer<T,IteratorFacade>,T,T&,std::ptrdiff_t,IteratorFacade> iterator;
+
+ typedef Dune::GenericIterator<const TestContainer<T,IteratorFacade>,const T,const T&,std::ptrdiff_t,IteratorFacade> const_iterator;
+
+ TestContainer(){
+ for(int i=0; i < 100; i++)
+ values_[i]=i;
+ }
+
+ iterator begin(){
+ return iterator(*this, 0);
+ }
+
+ const_iterator begin() const {
+ return const_iterator(*this, 0);
+ }
+
+ iterator end(){
+ return iterator(*this, 100);
+ }
+
+ const_iterator end() const {
+ return const_iterator(*this, 100);
+ }
+
+ T& operator[](int i){
+ return values_[i];
+ }
+
+
+ const T& operator[](int i) const {
+ return values_[i];
+ }
+private:
+ T values_[100];
+};
+
+#endif
--- /dev/null
+// -*- 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 "dummyiterator.hh"
+
+int main(){
+ // Check that iterator<T> can be compared with iterator<const T> as soon as
+ // a conversion from iterator<T> to iterator<const T> exists
+
+ int value = 0;
+ dummyiterator<int> mit(value);
+ dummyiterator<const int> cit(value);
+
+ bool result = mit == cit;
+
+ if(result) return 0;
+ else return 1;
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+
+#ifndef DUNE_ITERATORTEST_HH
+#define DUNE_ITERATORTEST_HH
+#include <iostream>
+#include <algorithm>
+#include <dune/common/typetraits.hh>
+#include <dune/common/unused.hh>
+
+/**
+ * @brief Tests the capabilities of a forward iterator.
+ * @param begin Iterator positioned at the start.
+ * @param end Iterator positioned at the end.
+ * @param opt Functor for doing whatever one wants.
+ */
+template<class Iter, class Opt>
+int testForwardIterator(Iter begin, Iter end, Opt& opt)
+{
+ //std::cout<< "forward: ";
+ Iter tmp=begin, tmp1(begin);
+ int ret=0;
+ if(tmp!=begin || tmp1!=begin || tmp!=tmp1) {
+ std::cerr<<" Copying iterator failed "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ret=1;
+ }
+
+ for(; begin!=end; ++begin)
+ opt(*begin);
+ //std::cout<< " OK "<<std::endl;
+ return ret;
+}
+
+/**
+ * @brief Tests the capabilities of a bidirectional iterator.
+ *
+ * Namely it test wether random positions can be reached from
+ * each directions.
+ *
+ * @param begin Iterator positioned at the stsrt.
+ * @param end Iterator positioned at the end.
+ * @param opt Functor for doing whatever one wants.
+ */
+template<class Iter, class Opt>
+int testBidirectionalIterator(Iter begin, Iter end, Opt opt)
+{
+ testForwardIterator(begin, end, opt);
+ Iter tbegin=--begin;
+ Iter tend=--end;
+ for(; tbegin!=tend; --tend)
+ opt(*tend);
+
+ typename Iter::difference_type size = std::distance(begin, end);
+ srand(300);
+
+ int no= (size>10) ? 10 : size;
+
+ for(int i=0; i < no; i++)
+ {
+ int index = static_cast<int>(size*(rand()/(RAND_MAX+1.0)));
+ int backwards=size-index;
+ tbegin=begin;
+ tend=end;
+ for(int j=0; j < index; j++) ++tbegin;
+ for(int j=0; j < backwards; j++) --tend;
+
+ if(tbegin != tend)
+ {
+ std::cerr<<"Did not reach same index by starting forward from "
+ <<"begin and backwards from end."<<std::endl;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+template<class Iter, class Opt>
+int testRandomAccessIterator(Iter begin, Iter end, Opt opt){
+ int ret=testBidirectionalIterator(begin, end, opt);
+
+ typename Iter::difference_type size = end-begin;
+
+ srand(300);
+
+ int no= (size>10) ? 10 : size;
+
+ for(int i=0; i < no; i++)
+ {
+ int index = static_cast<int>(size*(rand()/(RAND_MAX+1.0)));
+ opt(begin[index]);
+ }
+
+ // Test the less than operator
+ if(begin != end &&!( begin<end))
+ {
+ std::cerr<<"! (begin()<end())"<<std::endl;
+ ret++;
+ }
+
+ if(begin != end) {
+ if(begin-end >= 0) {
+ std::cerr<<"begin!=end, but begin-end >= 0!"<<std::endl;
+ ret++;
+ }
+ if(end-begin <= 0) {
+ std::cerr<<"begin!=end, but end-begin <= 0!"<<std::endl;
+ ret++;
+ }
+ }
+
+ for(int i=0; i < no; i++)
+ {
+ int index = static_cast<int>(size*(rand()/(RAND_MAX+1.0)));
+ Iter rand(begin), test(begin), res;
+ rand+=index;
+
+ if((res=begin+index) != rand)
+ {
+ std::cerr << " i+n should have the result i+=n, where i is the "
+ <<"iterator and n is the difference type!" <<std::endl;
+ ret++;
+ }
+ for(int i=0; i< index; i++) ++test;
+
+ if(test != rand)
+ {
+ std::cerr << "i+=n should have the same result as applying the"
+ << "increment ooperator n times!"<< std::cerr;
+ ret++;
+ }
+
+ rand=end, test=end;
+ rand-=index;
+
+
+ if((end-index) != rand)
+ {
+ std::cerr << " i-n should have the result i-=n, where i is the "
+ <<"iterator and n is the difference type!" <<std::endl;
+ ret++;
+ }
+ for(int i=0; i< index; i++) --test;
+
+ if(test != rand)
+ {
+ std::cerr << "i+=n should have the same result as applying the"
+ << "increment ooperator n times!"<< std::cerr;
+ ret++;
+ }
+ }
+
+ for(int i=0; i < no; i++)
+ {
+ Iter iter1 = begin+static_cast<int>(size*(rand()/(RAND_MAX+1.0)));
+ Iter iter2 = begin+static_cast<int>(size*(rand()/(RAND_MAX+1.0)));
+ typename Iter::difference_type diff = iter2 -iter1;
+ if((iter1+diff)!=iter2) {
+ std::cerr<< "i+(j-i) = j should hold, where i,j are iterators!"<<std::endl;
+ ret++;
+ }
+ }
+
+ return ret;
+}
+
+template<class Iter, class Opt, typename iterator_category>
+int testIterator(Iter& begin, Iter& end, Opt& opt, iterator_category cat);
+
+template<class Iter, class Opt>
+int testIterator(Iter& begin, Iter& end, Opt& opt, std::forward_iterator_tag)
+{
+ return testForwardIterator(begin, end, opt);
+}
+
+template<class Iter, class Opt>
+int testIterator(Iter& begin, Iter& end, Opt& opt, std::bidirectional_iterator_tag)
+{
+ return testBidirectionalIterator(begin, end, opt);
+}
+
+template<class Iter, class Opt>
+int testIterator(Iter& begin, Iter& end, Opt& opt, std::random_access_iterator_tag)
+{
+ // std::cout << "Testing iterator ";
+ int ret = testRandomAccessIterator(begin, end, opt);
+ //std::cout<<std::endl;
+ return ret;
+}
+
+template<class Iter, class Opt>
+int testConstIterator(Iter& begin, Iter& end, Opt& opt)
+{
+ //std::cout << "Testing constant iterator: ";
+ int ret=testIterator(begin, end, opt, typename std::iterator_traits<Iter>::iterator_category());
+ //std::cout<<std::endl;
+ return ret;
+}
+
+template<bool>
+struct TestSorting
+{
+ template<class Container, typename IteratorTag>
+ static void testSorting(Container&, IteratorTag)
+ {}
+ template<class Container>
+ static void testSorting(Container& c, std::random_access_iterator_tag)
+ {
+ std::sort(c.begin(), c.end());
+ }
+}
+;
+
+template<>
+struct TestSorting<false>
+{
+ template<class Container>
+ static void testSorting(Container& c, std::random_access_iterator_tag)
+ {}
+ template<class Container, typename IteratorTag>
+ static void testSorting(Container& c, IteratorTag tag)
+ {}
+};
+
+
+template<class Container, class Opt, bool testSort>
+int testIterator(Container& c, Opt& opt)
+{
+ typename Container::iterator begin=c.begin(), end=c.end();
+ typename Container::const_iterator cbegin(begin);
+ typename Container::const_iterator cbegin1 DUNE_UNUSED = begin;
+ typename Container::const_iterator cend=c.end();
+ int ret = 0;
+
+ TestSorting<testSort>::testSorting(c, typename std::iterator_traits<typename Container::iterator>::iterator_category());
+
+ if(end!=cend || cend!=end)
+ {
+ std::cerr<<"constant and mutable iterators should be equal!"<<std::endl;
+ ret=1;
+ }
+ ret += testConstIterator(cbegin, cend, opt);
+ if(testSort)
+ ret += testIterator(begin,end,opt);
+
+ return ret;
+}
+
+template<class Container, class Opt>
+int testIterator(Container& c, Opt& opt)
+{
+ return testIterator<Container,Opt,true>(c,opt);
+}
+
+template<class Iter, class Opt>
+void testAssignment(Iter begin, Iter end, Opt&)
+{
+ //std::cout << "Assignment: ";
+ for(; begin!=end; begin++)
+ *begin=typename std::iterator_traits<Iter>::value_type();
+ //std::cout<<" Done."<< std::endl;
+}
+
+template<class Iter, class Opt>
+int testIterator(Iter& begin, Iter& end, Opt& opt)
+{
+ testAssignment(begin, end, opt);
+ return testConstIterator(begin, end, opt);
+}
+
+
+template<class T>
+class Printer {
+ typename Dune::remove_const<T>::type res;
+public:
+ Printer() : res(0){}
+ void operator()(const T& t){
+ res+=t;
+ // std::cout << t <<" ";
+ }
+};
+
+template<class Container, class Opt>
+int testIterator(const Container& c, Opt& opt)
+{
+ typename Container::const_iterator begin=c.begin(), end=c.end();
+ return testConstIterator(begin,end, opt);
+}
+
+
+template<class Container>
+int testIterator(Container& c)
+{
+ Printer<typename std::iterator_traits<typename Container::iterator>::value_type> print;
+ return testIterator(c,print);
+}
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#include <assert.h>
+#include <iostream>
+#include <dune/common/lru.hh>
+#include <dune/common/parallel/mpihelper.hh>
+
+void lru_test()
+{
+ std::cout << "testing Dune::lru<int,double>\n";
+
+ Dune::lru<int, double> lru;
+ lru.insert(10, 1.0);
+ assert(lru.front() == lru.back());
+ lru.insert(11, 2.0);
+ assert(lru.front() == 2.0 && lru.back() == 1.0);
+ lru.insert(12, 99);
+ lru.insert(13, 1.3);
+ lru.insert(14, 12345);
+ lru.insert(15, -17);
+ assert(lru.front() == -17 && lru.back() == 1.0);
+ // update
+ lru.insert(10);
+ assert(lru.front() == 1.0 && lru.back() == 2.0);
+ // update
+ lru.touch(13);
+ assert(lru.front() == 1.3 && lru.back() == 2.0);
+ // remove item
+ lru.pop_front();
+ assert(lru.front() == 1.0 && lru.back() == 2.0);
+ // remove item
+ lru.pop_back();
+ assert(lru.front() == 1.0 && lru.back() == 99);
+
+ std::cout << "... passed\n";
+}
+
+int main (int argc, char** argv)
+{
+ Dune::MPIHelper::instance(argc,argv);
+
+ lru_test();
+
+ return 0;
+}
--- /dev/null
+// -*- 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 <dune/common/parallel/mpihelper.hh>
+
+#if HAVE_MPI
+#include <dune/common/parallel/mpicollectivecommunication.hh>
+#endif
+
+#include <iostream>
+int main(int argc, char** argv)
+{
+ typedef Dune::MPIHelper Helper;
+ Helper& mpi = Helper::instance(argc, argv);
+
+#if HAVE_MPI
+ {
+ typedef Helper::MPICommunicator MPIComm;
+ Dune::CollectiveCommunication<MPIComm> comm(mpi.getCommunicator());
+
+ enum { length = 5 };
+ double values[5];
+ for(int i=0; i<length; ++i) values[i] = 1.0;
+
+ double * commBuff = ((double *) &values[0]);
+ // calculate global sum
+ comm.sum( commBuff , length );
+
+ double val[length];
+ for(int i=0; i<length; ++i) val[i] = 1.0;
+ // calculate global sum by calling sum for each component
+ for(int i=0; i<length; ++i)
+ {
+ // this method works
+ val[i] = comm.sum( val[i] );
+ }
+
+ // result from above should be size of job
+#ifndef NDEBUG
+ double sum = mpi.size();
+#endif
+ for(int i=0; i<length; ++i)
+ {
+ assert( std::abs( values[i] - sum ) < 1e-8 );
+ assert( std::abs( val[i] - sum ) < 1e-8 );
+ }
+ }
+
+ std::cout << "We are at the end!"<<std::endl;
+#else
+ std::cout << "WARNING: test Dune::CollectiveCommunication<MPI_Comm> disabled because MPI not available! " << std::endl;
+ return 77;
+#endif
+ return 0;
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#include <config.h>
+
+#include <dune/common/parallel/mpihelper.hh>
+#include <dune/common/parallel/mpiguard.hh>
+
+int main(int argc, char** argv)
+{
+ Dune::MPIHelper & mpihelper = Dune::MPIHelper::instance(argc, argv);
+
+ if (mpihelper.rank() == 0)
+ std::cout << "---- default constructor" << std::endl;
+ try
+ {
+ // at the end of this block the guard is destroyed and possible exceptions are communicated
+ {
+ Dune::MPIGuard guard;
+ if (mpihelper.rank() > 0)
+ DUNE_THROW(Dune::Exception, "Fakeproblem on process " << mpihelper.rank());
+ guard.finalize();
+ }
+ }
+ catch (Dune::Exception & e)
+ {
+ std::cout << "Error (rank " << mpihelper.rank() << "): "
+ << e.what() << std::endl;
+ }
+
+ mpihelper.getCollectiveCommunication().barrier();
+ if (mpihelper.rank() == 0)
+ std::cout << "---- guard(MPI_COMM_WORLD)" << std::endl;
+ try
+ {
+#if HAVE_MPI
+ // at the end of this block the guard is destroyed and possible exceptions are communicated
+ {
+ Dune::MPIGuard guard(MPI_COMM_WORLD);
+ if (mpihelper.rank() > 0)
+ DUNE_THROW(Dune::Exception, "Fakeproblem on process " << mpihelper.rank());
+ guard.finalize();
+ }
+#else
+ std::cout << "Info: no mpi used\n";
+#endif
+ }
+ catch (Dune::Exception & e)
+ {
+ std::cout << "Error (rank " << mpihelper.rank() << "): "
+ << e.what() << std::endl;
+ }
+
+ mpihelper.getCollectiveCommunication().barrier();
+ if (mpihelper.rank() == 0)
+ std::cout << "---- guard(MPIHelper)" << std::endl;
+ try
+ {
+ // at the end of this block the guard is destroyed and possible exceptions are communicated
+ {
+ Dune::MPIGuard guard(mpihelper);
+ if (mpihelper.rank() > 0)
+ DUNE_THROW(Dune::Exception, "Fakeproblem on process " << mpihelper.rank());
+ guard.finalize();
+ }
+ }
+ catch (Dune::Exception & e)
+ {
+ std::cout << "Error (rank " << mpihelper.rank() << "): "
+ << e.what() << std::endl;
+ }
+
+
+ mpihelper.getCollectiveCommunication().barrier();
+ if (mpihelper.rank() == 0)
+ std::cout << "---- manual error" << std::endl;
+ try
+ {
+ // at the end of this block the guard is destroyed and possible exceptions are communicated
+ {
+ Dune::MPIGuard guard;
+ guard.finalize(mpihelper.rank() > 0);
+ }
+ }
+ catch (Dune::Exception & e)
+ {
+ std::cout << "Error (rank " << mpihelper.rank() << "): "
+ << e.what() << std::endl;
+ }
+
+ mpihelper.getCollectiveCommunication().barrier();
+ if (mpihelper.rank() == 0)
+ std::cout << "---- done" << std::endl;
+}
--- /dev/null
+// -*- 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 <dune/common/parallel/mpihelper.hh>
+#include <iostream>
+
+int main(int argc, char** argv)
+{
+
+#ifdef MPIHELPER_PREINITIALIZE
+#if HAVE_MPI
+ MPI_Init(&argc, &argv);
+#endif
+#endif
+
+ typedef Dune::MPIHelper Helper;
+
+ {
+ Helper& mpi = Helper::instance(argc, argv);
+
+ Helper::MPICommunicator comm DUNE_UNUSED = mpi.getCommunicator();
+ comm= mpi.getCommunicator();
+ }
+
+ {
+ Helper& mpi = Helper::instance(argc, argv);
+
+ Helper::MPICommunicator comm DUNE_UNUSED = mpi.getCommunicator();
+ comm= mpi.getCommunicator();
+
+#ifdef MPIHELPER_PREINITIALIZE
+#if HAVE_MPI
+ MPI_Finalize();
+#endif
+#endif
+ }
+ std::cout << "We are at the end!"<<std::endl;
+
+}
--- /dev/null
+// -*- 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 <dune/common/nullptr.hh>
+
+void basic_tests()
+{
+ typedef Dune::nullptr_t NULLPTR_T;
+ char* ch = nullptr; // ch has the null pointer value
+ char* ch2 = 0; // ch2 has the null pointer value
+#ifdef FAIL
+ int n = nullptr; // error
+ ++n;
+#endif
+ int n2 = 0; // n2 is zero
+ if( ch == 0 ) ; // evaluates to true
+ if( ch == nullptr ) ; // evaluates to true
+ if( nullptr == ch ) ; // evaluates to true
+ if( ch ) ; // evaluates to false
+ if( n2 == 0 ) ; // evaluates to true
+ ch = ch2;
+#ifdef FAIL
+ if( n2 == nullptr ) ; // error
+ if( nullptr ) ; // error, no conversion to bool
+ if( nullptr == 0 ) ; // error
+ // arithmetic
+ nullptr = 0; // error, nullptr is not an lvalue
+ nullptr + 2; // error
+#endif
+}
+
+int main()
+{
+ basic_tests();
+ return 0;
+}
--- /dev/null
+// -*- 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 <dune/common/nullptr.hh>
--- /dev/null
+// -*- 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 <sstream>
+#include <dune/common/parametertree.hh>
+#include <dune/common/parametertreeparser.hh>
+
+template<class P>
+void testparam(const P & p)
+{
+ // try accessing key
+ std::cout << p.template get<int>("x1") << std::endl;
+ std::cout << p.template get<double>("x1") << std::endl;
+ std::cout << p.template get<std::string>("x2") << std::endl;
+ std::cout << p.template get<bool>("x3") << std::endl;
+ // try reading array like structures
+ std::vector<unsigned int>
+ array1 = p.template get< std::vector<unsigned int> >("array");
+#ifndef NDEBUG
+ Dune::array<unsigned int, 8>
+ array2 = p.template get< Dune::array<unsigned int, 8> >("array");
+ Dune::FieldVector<unsigned int, 8>
+ array3 = p.template get< Dune::FieldVector<unsigned int, 8> >("array");
+#endif
+ assert(array1.size() == 8);
+ std::cout << "array =";
+ for (unsigned int i=0; i<8; i++)
+ {
+ assert(array1[i] == i+1);
+ assert(array2[i] == i+1);
+ assert(array3[i] == i+1);
+ std::cout << "\t" << array1[i];
+ }
+ std::cout << std::endl;
+ // try accessing subtree
+ p.sub("Foo");
+ p.sub("Foo").template get<std::string>("peng");
+ // check hasSub and hasKey
+ assert(p.hasSub("Foo"));
+ assert(!p.hasSub("x1"));
+ assert(p.hasKey("x1"));
+ assert(!p.hasKey("Foo"));
+ // try accessing inexistent key
+ try {
+ p.template get<int>("bar");
+ DUNE_THROW(Dune::Exception, "failed to detect missing key");
+ }
+ catch (Dune::RangeError & r) {}
+ // try accessing inexistent subtree
+ try {
+ p.sub("bar");
+ DUNE_THROW(Dune::Exception, "failed to detect missing subtree");
+ }
+ catch (Dune::RangeError & r) {}
+ // try accessing key as subtree
+ try {
+ p.sub("x1");
+ DUNE_THROW(Dune::Exception, "succeeded to access key as subtree");
+ }
+ catch (Dune::RangeError & r) {}
+ // try accessing subtree as key
+ try {
+ p.template get<double>("Foo");
+ DUNE_THROW(Dune::Exception, "succeeded to access subtree as key");
+ }
+ catch (Dune::RangeError & r) {}
+}
+
+template<class P>
+void testmodify(P parameterSet)
+{
+ parameterSet["testDouble"] = "3.14";
+ parameterSet["testInt"] = "42";
+ parameterSet["testString"] = "Hallo Welt!";
+ parameterSet["testVector"] = "2 3 5 7 11";
+ parameterSet.sub("Foo")["bar"] = "2";
+
+ double testDouble = parameterSet.template get<double>("testDouble");
+ int testInt = parameterSet.template get<int>("testInt");
+ ++testDouble;
+ ++testInt;
+ std::string testString = parameterSet.template get<std::string>("testString");
+ typedef Dune::FieldVector<unsigned, 5> FVector;
+ FVector testFVector = parameterSet.template get<FVector>("testVector");
+ typedef std::vector<unsigned> SVector;
+ SVector testSVector = parameterSet.template get<SVector>("testVector");
+ if(testSVector.size() != 5)
+ DUNE_THROW(Dune::Exception, "Testing std::vector<unsigned>: expected "
+ "size()==5, got size()==" << testSVector.size());
+ for(unsigned i = 0; i < 5; ++i)
+ if(testFVector[i] != testSVector[i])
+ DUNE_THROW(Dune::Exception,
+ "testFVector[" << i << "]==" << testFVector[i] << " but "
+ "testSVector[" << i << "]==" << testSVector[i]);
+ if (parameterSet.template get<std::string>("Foo.bar") != "2")
+ DUNE_THROW(Dune::Exception, "Failed to write subtree entry");
+ if (parameterSet.sub("Foo").template get<std::string>("bar") != "2")
+ DUNE_THROW(Dune::Exception, "Failed to write subtree entry");
+}
+
+int main()
+{
+ try {
+ // read config
+ std::stringstream s;
+ s << "x1 = 1 # comment\n"
+ << "x2 = hallo\n"
+ << "x3 = no\n"
+ << "array = 1 2 3 4 5\t6 7 8\n"
+ << "\n"
+ << "[Foo]\n"
+ << "peng = ligapokal\n";
+
+ Dune::ParameterTree c;
+ Dune::ParameterTreeParser::readINITree(s, c);
+
+ // test modifying and reading
+ testmodify<Dune::ParameterTree>(c);
+ try {
+ c.get<int>("testInt");
+ DUNE_THROW(Dune::Exception, "unexpected shallow copy of ParameterTree");
+ }
+ catch (Dune::RangeError & r) {}
+
+ // more const tests
+ testparam<Dune::ParameterTree>(c);
+ }
+ catch (Dune::Exception & e)
+ {
+ std::cout << e << std::endl;
+ return 1;
+ }
+ return (0);
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <iostream>
+#include <ostream>
+#include <string>
+
+#include <dune/common/exceptions.hh>
+#include <dune/common/ios_state.hh>
+#include <dune/common/path.hh>
+
+void setCode(int& code, bool status) {
+ if(!status)
+ code = 1;
+ else
+ if(code == 77)
+ code = 0;
+}
+
+void concatPathsTests(int& code) {
+ typedef const char* const triple[3];
+ static const triple data[] = {
+ {"a" , "b" , "a/b" },
+ {"/a", "b" , "/a/b"},
+ {"a/", "b" , "a/b" },
+ {"a" , "b/", "a/b/"},
+ {"..", "b" , "../b"},
+ {"a" , "..", "a/.."},
+ {"." , "b" , "./b" },
+ {"a" , "." , "a/." },
+ {"" , "b" , "b" },
+ {"a" , "" , "a" },
+ {"" , "" , "" },
+ {NULL, NULL, NULL }
+ };
+ for(const triple* p = data; (*p)[0] != NULL; ++p) {
+ const std::string& result = Dune::concatPaths((*p)[0], (*p)[1]);
+ bool success = result == (*p)[2];
+ setCode(code, success);
+ if(!success)
+ std::cerr << "concatPaths(\"" << (*p)[0] << "\", "
+ << "\"" << (*p)[1] << "\"): got \"" << result << "\", "
+ << "expected \"" << (*p)[2] << "\"" << std::endl;
+ }
+}
+
+void processPathTests(int& code) {
+ typedef const char* const pair[3];
+ static const pair data[] = {
+ {"" , "" },
+ {"." , "" },
+ {"./" , "" },
+ {"a/.." , "" },
+ {".." , "../" },
+ {"../a" , "../a/"},
+ {"a" , "a/" },
+ {"a//" , "a/" },
+ {"a///b" , "a/b/" },
+ {"/" , "/" },
+ {"/." , "/" },
+ {"/.." , "/" },
+ {"/a/.." , "/" },
+ {"/a" , "/a/" },
+ {"/a/" , "/a/" },
+ {"/../a/", "/a/" },
+ {NULL , NULL }
+ };
+ for(const pair* p = data; (*p)[0] != NULL; ++p) {
+ const std::string& result = Dune::processPath((*p)[0]);
+ bool success = result == (*p)[1];
+ setCode(code, success);
+ if(!success)
+ std::cerr << "processPath(\"" << (*p)[0] << "\"): got "
+ << "\"" << result << "\", expected "
+ << "\"" << (*p)[1] << "\"" << std::endl;
+ }
+}
+
+void prettyPathTests(int& code) {
+ struct triple {
+ const char* p;
+ bool isDir;
+ const char* result;
+ };
+ static const triple data[] = {
+ {"" , true , "." },
+ {"" , false, "." },
+ {"." , true , "." },
+ {"." , false, "." },
+ {"./" , true , "." },
+ {"./" , false, "." },
+ {"a/.." , true , "." },
+ {"a/.." , false, "." },
+ {".." , true , ".." },
+ {".." , false, ".." },
+ {"../a" , true , "../a/"},
+ {"../a" , false, "../a" },
+ {"a" , true , "a/" },
+ {"a" , false, "a" },
+ {"a//" , true , "a/" },
+ {"a//" , false, "a" },
+ {"a///b" , true , "a/b/" },
+ {"a///b" , false, "a/b" },
+ {"/" , true , "/" },
+ {"/" , false, "/" },
+ {"/." , true , "/" },
+ {"/." , false, "/" },
+ {"/.." , true , "/" },
+ {"/.." , false, "/" },
+ {"/a/.." , true , "/" },
+ {"/a/.." , false, "/" },
+ {"/a" , true , "/a/" },
+ {"/a" , false, "/a" },
+ {"/a/" , true , "/a/" },
+ {"/a/" , false, "/a" },
+ {"/../a/", true , "/a/" },
+ {"/../a/", false, "/a" },
+ {NULL, false, NULL }
+ };
+
+ Dune::ios_base_all_saver state(std::cerr);
+ std::cerr << std::boolalpha;
+
+ for(const triple* p = data; p->p != NULL; ++p) {
+ const std::string& result = Dune::prettyPath(p->p, p->isDir);
+ bool success = result == p->result;
+ setCode(code, success);
+ if(!success)
+ std::cerr << "prettyPath(\"" << p->p << "\", " << p->isDir << "): got "
+ << "\"" << result << "\", expected \"" << p->result << "\""
+ << std::endl;
+ }
+}
+
+void relativePathTests(int& code) {
+ typedef const char* const triple[3];
+ static const triple data[] = {
+ {"" , "" , "" },
+ {"" , "b" , "b/" },
+ {"" , "..", "../" },
+ {"a" , "" , "../" },
+ {"a" , "b" , "../b/"},
+ {"/" , "/" , "" },
+ {"/a", "/" , "../" },
+ {"/" , "/b", "b/" },
+ {"/a", "/b", "../b/"},
+ {NULL, NULL, NULL }
+ };
+
+ for(const triple* p = data; (*p)[0] != NULL; ++p) {
+ const std::string& result = Dune::relativePath((*p)[0], (*p)[1]);
+ bool success = result == (*p)[2];
+ setCode(code, success);
+ if(!success)
+ std::cerr << "relativePath(\"" << (*p)[0] << "\", "
+ << "\"" << (*p)[1] << "\"): got \"" << result << "\", "
+ << "expected \"" << (*p)[2] << "\"" << std::endl;
+ }
+
+ typedef const char* const pair[2];
+ static const pair except_data[] = {
+ {"" , "/" },
+ {"a" , "/" },
+ {"/" , "" },
+ {"/" , "b" },
+ {"..", "" },
+ {NULL, NULL}
+ };
+
+ for(const pair* p = except_data; (*p)[0] != NULL; ++p) {
+ std::string result;
+ try {
+ result = Dune::relativePath((*p)[0], (*p)[1]);
+ }
+ catch(const Dune::NotImplemented&) {
+ setCode(code, true);
+ continue;
+ }
+ setCode(code, false);
+ std::cerr << "relativePath(\"" << (*p)[0] << "\", "
+ << "\"" << (*p)[1] << "\"): got \"" << result << "\", "
+ << "expected exception thrown" << std::endl;
+ }
+}
+
+int main ()
+{
+ try {
+ int code = 77;
+
+ concatPathsTests(code);
+ processPathTests(code);
+ prettyPathTests(code);
+ relativePathTests(code);
+
+ return code;
+ }
+ catch(const Dune::Exception& e) {
+ std::cerr << "Exception thrown: " << e << std::endl;
+ throw;
+ }
+}
--- /dev/null
+// -*- 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 <dune/common/poolallocator.hh>
+#include <dune/common/alignment.hh>
+#include <dune/common/fmatrix.hh>
+
+using namespace Dune;
+
+struct UnAligned
+{
+ char t;
+ char s;
+ char k;
+};
+
+
+
+template<std::size_t size, typename T>
+struct testPoolMain
+{
+ static int test()
+ {
+ int ret=0;
+
+ Pool<T,size> pool;
+
+ int elements = Pool<T,size>::elements;
+ //int poolSize = Pool<T,size>::size;
+ //int chunkSize = Pool<T,size>::chunkSize;
+ //int alignedSize = Pool<T,size>::alignedSize;
+
+ unsigned long* oelements = new unsigned long[10*elements];
+
+ typedef typename Pool<T,size>::Chunk Chunk;
+
+ //Fill 10 chunks
+ for(int chunk=0; chunk < 10; ++chunk) {
+ //std::cout<< std::endl<<"Chunk "<<chunk<<" ";
+ unsigned long element = reinterpret_cast<unsigned long>(pool.allocate());
+ //void* celement = reinterpret_cast<void*>(element);
+ //std::cout << element<<" "<< celement<<", "<<std::endl;
+
+ Chunk* currentChunk = pool.chunks_;
+
+ assert(element==reinterpret_cast<unsigned long>(currentChunk->memory_));
+ unsigned long end = reinterpret_cast<unsigned long>(currentChunk->chunk_)+Pool<T,size>::chunkSize;
+
+ if(element< reinterpret_cast<unsigned long>(currentChunk->chunk_))
+ {
+ std::cerr <<" buffer overflow during first alloc: "<<reinterpret_cast<unsigned long>(currentChunk->chunk_)
+ <<">"<<element<<"+"<<sizeof(T)<<std::endl;
+ return ++ret;
+ }
+
+ if(end < element + sizeof(T)) {
+ std::cerr <<" buffer overflow during first alloc: "<<end<<"<"<<element<<"+"<<sizeof(T)<<std::endl;
+ return ++ret;
+ }
+
+ oelements[chunk*elements]=element;
+
+ for(int i=1; i < elements; i++)
+ {
+ element = reinterpret_cast<unsigned long>(pool.allocate());
+ //celement = reinterpret_cast<void*>(element);
+ //std::cout << element<<" "<<celement<<", "<<std::endl;
+
+ if(element< reinterpret_cast<unsigned long>(currentChunk->chunk_)) {
+ std::cerr <<" buffer underflow during first alloc: "<<reinterpret_cast<unsigned long>(currentChunk->chunk_)
+ <<">"<<element<<"+"<<sizeof(T)<<std::endl;
+ return ++ret;
+ }
+
+ if(end < element + sizeof(T)) {
+ std::cerr <<" buffer overflow during "<<i<<" alloc: "<<end<<"<"<<element+sizeof(T)<<std::endl;
+ return ++ret;
+
+ }
+
+ if(oelements[chunk*elements+i-1]+sizeof(T)>element) {
+ std::cerr<<"allocated elements overlap!"<<std::endl;
+ return ++ret;
+ }
+
+ oelements[chunk*elements+i]=element;
+ }
+ }
+
+
+
+ for(int i=0; i < elements*10; ++i)
+ pool.free(reinterpret_cast<void*>(oelements[i]));
+ delete[] oelements;
+
+ return ret;
+ }
+};
+
+template<typename T>
+int testPool()
+{
+ const std::size_t size = sizeof(T)>=2 ? sizeof(T)-2 : 0;
+
+ int ret=0;
+
+ std::cout<<"Checking "<<typeid(T).name()<<" sizeof="<<sizeof(T)<<" with size "<< size<<
+ " alignment="<<AlignmentOf<T>::value<<std::endl;
+
+ ret += testPoolMain<0,T>::test();
+ ret += testPoolMain<size,T>::test();
+ ret += testPoolMain<5*size,T>::test();
+ ret += testPoolMain<11*size,T>::test();
+ ret += testPoolMain<33*size,T>::test();
+
+ return ret;
+}
+
+int testPoolAllocator()
+{
+ int ret=0;
+ PoolAllocator<double,10> pool;
+ double *d=pool.allocate(1);
+ PoolAllocator<float,5> pool1=pool;
+ PoolAllocator<double,10> pool2=pool;
+ try
+ {
+ pool2.deallocate(d,1);
+#ifndef NDEBUG
+ ++ret;
+ std::cerr<<"ERROR: deallocation should not work with copied allocators."<<std::endl;
+#endif
+ }
+ catch(std::bad_alloc)
+ {}
+ pool1.allocate(1);
+ double *d1=pool2.allocate(1);
+ pool.deallocate(d,1);
+ pool2.deallocate(d1,1);
+ pool2.allocate(1);
+ return ret;
+}
+int main(int, char **)
+{
+ int ret=0;
+
+ ret += testPool<int>();
+
+ ret+= testPool<double>();
+
+ ret+= testPool<char>();
+
+ ret += testPool<Dune::FieldMatrix<double,10,10> >();
+
+ ret+=testPoolAllocator();
+
+ std::cout<<AlignmentOf<UnAligned>::value<<" "<<sizeof(UnAligned)<<std::endl;
+
+ ret += testPool<UnAligned>();
+
+ return ret;
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+
+// $Id$
+
+// make sure assert works even when not compiling for debugging
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(DISABLE_CONFIGURED_SHARED_PTR) && defined(SHARED_PTR_NAMESPACE)
+#undef SHARED_PTR_NAMESPACE
+#undef HAVE_MAKE_SHARED
+#endif
+
+#include <dune/common/classname.hh>
+#include <dune/common/shared_ptr.hh>
+
+#include <cassert>
+#include <cstdlib>
+#include <iostream>
+#include <ostream>
+#include <vector>
+
+template<class T>
+class Deleter
+{
+public:
+ Deleter(bool& deleted) :
+ deleted_(deleted)
+ {}
+
+ void operator() (T* p) const
+ {
+ delete p;
+ deleted_ = true;
+ }
+
+private:
+ bool& deleted_;
+};
+
+class A {};
+class B : public A {};
+class C : A {};
+
+
+Dune::shared_ptr<A> test_make_shared()
+{
+ return Dune::make_shared<B>();
+}
+
+
+int main(){
+ using namespace Dune;
+ int ret=0;
+ {
+ // test default constructor
+ shared_ptr<int> foo;
+
+ // test conversion in make_shared
+ shared_ptr<A> a=test_make_shared();
+
+ {
+ shared_ptr<B> b(new B);
+ a=b;
+
+ if(b.use_count()!=2) {
+ std::cout << "Reference count is wrong! "<<__LINE__<<":"<<
+ __FILE__<<std::endl;
+ ret=1;
+ }
+
+ if(a.use_count()!=2) {
+ std::cout << "Reference count is wrong! "<<__LINE__<<":"<<
+ __FILE__<<std::endl;
+ ret=1;
+ }
+
+ }
+ // print the type of the shared_ptr, so we know whether we are
+ // checking dune's shared_ptr or some std one
+ std::cout << "=== checking shared_ptr type: " << className(foo)
+ << std::endl;
+
+ // make sure default-constructed shared_ptr values can be copied
+ {
+ shared_ptr<int> bar(foo);
+ shared_ptr<int> baz;
+ baz = foo;
+ }
+
+ // test cast-to-bool
+ if (foo) {
+ std::cout << "Default constructor doesn't create a NULL pointer!" << std::endl;
+ ret=1;
+ }
+
+ // test custom deleter
+ bool deleted = false;
+ {
+ shared_ptr<int> foo(new int(1), Deleter<int>(deleted));
+
+ //test if deleter is called
+ deleted = false;
+ foo.reset(new int(2)); // this should call the deleter in the constructor
+ if (not (deleted))
+ {
+ std::cout << "Custom deleter not called!" << std::endl;
+ ret=1;
+ }
+
+ //test if old deleter is not called
+ deleted = false;
+ foo.reset(); // this should call no deleter
+ if (deleted)
+ {
+ std::cout << "Old deleter was called!" << std::endl;
+ ret=1;
+ }
+
+ //test if old deleter is not called
+ deleted = false;
+ foo.reset(new int(3), Deleter<int>(deleted)); // this should call no deleter
+ if (deleted)
+ {
+ std::cout << "Old deleter was called!" << std::endl;
+ ret=1;
+ }
+ // going out of scope should call the deleter
+ }
+ if (not (deleted))
+ {
+ std::cout << "Custom deleter not called!" << std::endl;
+ ret=1;
+ }
+ {
+ shared_ptr<int> foo(new int(1), Deleter<int>(deleted));
+
+ foo.reset(new int(4)); // this should call the deleter...
+
+ deleted = false;
+ // ... but going out of scope should call no deleter
+ }
+ if (deleted)
+ {
+ std::cout << "1Old deleter was called!" << std::endl;
+ ret=1;
+ }
+
+ // test constructor from a given pointer
+ shared_ptr<double> bar(new double(43.0));
+ assert(bar);
+
+ // test constructor from nullptr
+#if defined(SHARED_PTR_HEADER) && !defined(HAVE_NULLPTR)
+ #warning Construction of shared_ptr from a nullptr will not work as compiler
+ #warning does not support the latter.
+ shared_ptr<double> bar_null=shared_ptr<double>();
+#else
+ shared_ptr<double> bar_null(nullptr);
+#endif
+ assert(!bar_null);
+ assert(!bar_null.get());
+
+ // test reset()
+ bar.reset();
+ assert(!bar);
+
+ // test get() for empty shared_ptr
+ assert(!bar.get());
+
+ // test reset(T*)
+ double* p = new double(44.0);
+ bar.reset(p);
+ assert(bar);
+ assert(bar.use_count()==1);
+
+ // test get()
+ double* barPtr = bar.get();
+ assert(barPtr==p);
+
+ // test constructor from a given pointer
+ shared_ptr<double> b(new double(42.0));
+ {
+ shared_ptr<double> d(b);
+ *b = 7;
+ }
+
+ if(b.use_count()!=1) {
+ std::cout << "Reference count is wrong! "<<__LINE__<<":"<<
+ __FILE__<<std::endl;
+ ret=1;
+ }
+ {
+ shared_ptr<double> c(b);
+
+ if(*b!=*c) {
+ std::cerr<<"References do not match! "<<__LINE__<<":"<<
+ __FILE__<<std::endl;
+ ret=1;
+ }
+ if(b.use_count()!=2 || c.use_count()!=2) {
+ std::cout << "Reference count is wrong! "<<__LINE__<<":"<<
+ __FILE__<<std::endl;
+ ret=1;
+ }
+ *b=8;
+ if(*b!=8 || *c!=8) {
+ std::cout<<"Assigning new value failed! "<<__LINE__<<":"<<
+ __FILE__<<std::endl;
+ ret=1;
+ }
+ }
+
+ if(b.use_count()!=1) {
+ std::cout << "Reference count is wrong! "<<__LINE__<<":"<<
+ __FILE__<<std::endl;
+ ret=1;
+ }
+
+ // test assignment from null ptr
+ // (should trigger FS 936, needs valgrind to check)
+ {
+ shared_ptr<int> foo = shared_ptr<int>(new int(42));
+ shared_ptr<int> bar; //null ptr
+
+ foo = bar; // should release memory held by foo
+ }
+
+ // test shared_ptr for stack allocation
+ {
+ int i = 10;
+ shared_ptr<int> pi = stackobject_to_shared_ptr(i);
+ }
+
+ // test shared_ptr for stack allocation with down cast
+ {
+ B b;
+ shared_ptr<A> pa = stackobject_to_shared_ptr<A>(b);
+#ifdef SHARED_PTR_COMPILE_FAIL
+ C c;
+ pa = stackobject_to_shared_ptr<A>(c); // A is an inaccessible base of C
+#endif
+ }
+ }
+ return (ret);
+}
--- /dev/null
+// -*- 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 <dune/common/singleton.hh>
+#include <iostream>
+class Foo : public Dune::Singleton<Foo>
+{
+public:
+ Foo()
+ {
+ bytes = new char[1000];
+ }
+
+ ~Foo()
+ {
+ delete[] bytes;
+ }
+private:
+ char* bytes;
+};
+
+class Foo1
+{
+public:
+ Foo1()
+ {
+ bytes = new char[1000];
+ }
+
+ ~Foo1()
+ {
+ delete[] bytes;
+ }
+private:
+ char* bytes;
+};
+
+typedef Dune::Singleton<Foo1> FooSingleton;
+
+
+Foo* globalFoo = 0;
+Foo1* globalFoo1 = 0;
+
+void setFoo()
+{
+ globalFoo = &Foo::instance();
+}
+
+
+void setFoo1()
+{
+ globalFoo1 = &FooSingleton::instance();
+}
+
+int testFoo()
+{
+ if(globalFoo != &Foo::instance()) {
+ std::cerr<<" Foo is not a real singleton!"<<std::endl;
+ return 1;
+ }
+ return 0;
+}
+
+
+int testFoo1()
+{
+ if(globalFoo1 != &FooSingleton::instance()) {
+ std::cerr<<" Foo is not a real singleton!"<<std::endl;
+ return 1;
+ }
+ return 0;
+}
+
+int main()
+{
+ int ret=0;
+ {
+ Foo& foo = Foo::instance();
+ Foo& foo1 = Foo::instance();
+ if(&foo!=&foo1) {
+ std::cerr<<" Foo is not a real singleton!"<<std::endl;
+ ++ret;
+ }
+ }
+ setFoo();
+ ret += testFoo();
+ {
+ Foo1& foo = FooSingleton::instance();
+ Foo1& foo1 = FooSingleton::instance();
+ if(&foo!=&foo1) {
+ std::cerr<<" Foo is not a real singleton!"<<std::endl;
+ ++ret;
+ }
+ }
+ setFoo1();
+ return ret += testFoo1();
+}
--- /dev/null
+// -*- 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
+
+#warning sllist is known to fail with some optimization flags (FS493)
+
+#include <dune/common/sllist.hh>
+#include <dune/common/test/iteratortest.hh>
+#include <dune/common/poolallocator.hh>
+#include <iostream>
+
+class DoubleWrapper
+{
+public:
+ DoubleWrapper(double b)
+ : d(b)
+ {
+ std::cout<<"Constructed "<<this<<std::endl;
+ }
+
+ DoubleWrapper()
+ : d()
+ {
+ std::cout<<"Constructed "<<this<<std::endl;
+ }
+
+ DoubleWrapper(const DoubleWrapper& other)
+ : d(other.d)
+ {
+ std::cout<<"Copied "<<this<<" from "<<&other<<std::endl;
+ }
+
+ ~DoubleWrapper()
+ {
+ std::cout<<"Destructing "<<this<<std::endl;
+ }
+
+ operator double() const
+ {
+ return d;
+ }
+
+ bool operator==(const DoubleWrapper& other) const
+ {
+ return d == other.d;
+ }
+
+
+ bool operator!=(const DoubleWrapper& other) const
+ {
+ return d != other.d;
+ }
+
+private:
+ double d;
+};
+
+typedef Dune::PoolAllocator<int,8*1024-16> IntAllocator;
+//typedef std::allocator<int> IntAllocator;
+typedef Dune::PoolAllocator<double,8*1024-16> DoubleAllocator;
+//typedef std::allocator<double> DoubleAllocator;
+typedef Dune::PoolAllocator<DoubleWrapper,8*1024-16> DoubleWAllocator;
+//typedef std::allocator<DoubleWrapper> DoubleWAllocator;
+
+template<typename T, typename A>
+const T& tail(const Dune::SLList<T,A>& alist)
+{
+ typedef typename Dune::SLList<T,A>::const_iterator Iterator;
+ Iterator tail=alist.begin();
+
+ for(int i = alist.size() - 1; i > 0; --i)
+ ++tail;
+ return *tail;
+}
+
+template<typename T,class A>
+int check(const Dune::SLList<T,A>& alist, const T* vals)
+{
+ typedef typename Dune::SLList<T,A>::const_iterator iterator;
+ int i=0;
+ for(iterator iter = alist.begin(); iter != alist.end(); ++iter, i++) {
+ if( vals[i] != *iter ) {
+ std::cerr<<" List missmatch! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+template<typename T,class A>
+void randomizeListBack(Dune::SLList<T,A>& alist){
+ using namespace Dune;
+
+ srand(300);
+
+ int lowest=0, highest=1000, range=(highest-lowest)+1;
+
+ T vals[10];
+
+ for(int i=0; i < 10; i++) {
+ T d = T(range*(rand()/(RAND_MAX+1.0)));
+ alist.push_back(d);
+ vals[i]=d;
+ }
+
+ check(alist, vals);
+}
+
+template<typename T,class A>
+void randomizeListFront(Dune::SLList<T,A>& alist){
+ using namespace Dune;
+
+ srand(300);
+ T vals[10];
+
+ int lowest=0, highest=1000, range=(highest-lowest)+1;
+
+ for(int i=0; i < 10; i++) {
+ T d = T(range*(rand()/(RAND_MAX+1.0)));
+ alist.push_front(d);
+ vals[9-i]=d;
+ }
+
+ check(alist, vals);
+}
+int testAssign()
+{
+ typedef Dune::SLList<int,IntAllocator> List;
+ List alist, blist;
+
+ alist.push_back(3);
+ alist.push_back(4);
+ alist.push_back(5);
+
+ blist.push_back(-1);
+
+ blist=alist;
+ List::iterator biter=blist.begin(), aiter=alist.begin();
+ for(; aiter!=alist.end(); ++aiter, ++biter)
+ if(*aiter!=*biter) {
+ std::cerr<<"Asignment failed "<<__FILE__<<":"<<__LINE__<<std::endl;
+ return 1;
+ }
+ return 0;
+}
+
+int testDelete()
+{
+ typedef Dune::SLList<int,IntAllocator> List;
+ List alist;
+
+ alist.push_back(3);
+ alist.push_back(4);
+ alist.push_back(5);
+
+ List::ModifyIterator iter = alist.beginModify();
+ iter.remove();
+ if(*(alist.begin())!=4) {
+ std::cerr<<"delete next on position before head failed! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ return 1;
+ }
+ if(*iter!=4) {
+ std::cerr<<"delete next failed! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ return 1;
+ }
+ ++iter;
+ iter.remove();
+ if(iter!=alist.end()) {
+ std::cerr<<"delete next failed! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ return 1;
+ }
+ if(tail(alist)!=4) {
+ std::cerr<<"delete before tail did not change tail! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ }
+
+ return 0;
+}
+
+int testEmpty()
+{
+ typedef Dune::SLList<int,DoubleAllocator> List;
+ int ret = 0;
+
+ List alist;
+ if(!alist.empty()) {
+ std::cerr<<"Newly created list not empty! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ret++;
+ }
+
+ if(0 != alist.size()) {
+ std::cerr<<"Newly created list not empty! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ret++;
+ }
+
+ randomizeListBack(alist);
+
+
+ if(alist.empty()) {
+ std::cerr<<"Randomized list is empty! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ret++;
+ }
+
+ if(0 == alist.size()) {
+ std::cerr<<"Randomized list is empty! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ret++;
+ }
+
+ for(int elements=alist.size(); elements>0; --elements)
+ alist.pop_front();
+
+ if(!alist.empty()) {
+ std::cerr<<"Emptied list not empty! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ret++;
+ }
+
+ if(0 != alist.size()) {
+ std::cerr<<"Emptied list not empty! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ret++;
+ }
+
+
+ if(ret!=0)
+ // Skip next tests
+ return ret;
+
+ randomizeListFront(alist);
+
+ if(alist.empty()) {
+ std::cerr<<"Randomized list is empty! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ret++;
+ }
+
+ if(0 == alist.size()) {
+ std::cerr<<"Randomized list is empty! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ret++;
+ }
+
+ alist.clear();
+
+ if(!alist.empty()) {
+ std::cerr<<"Emptied list not empty! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ret++;
+ }
+
+ if(0 != alist.size()) {
+ std::cerr<<"Emptied list not empty! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ret++;
+ }
+ return ret;
+
+}
+
+int testInsert()
+{
+ typedef Dune::SLList<int,IntAllocator> List;
+ //typedef Dune::SLList<int> List;
+
+ List alist;
+
+ alist.push_back(3);
+ List::ModifyIterator iter=alist.beginModify();
+ iter.insert(7);
+ int ret=0;
+
+ if(*iter!=3) {
+ std::cerr<<"Value at current position changed due to insert! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ret++;
+ }
+
+ if(*alist.begin()!=7) {
+ std::cerr<<"Insert did not change first element! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ret++;
+ }
+
+ iter=alist.beginModify();
+ iter.insert(5);
+
+ if(iter==alist.end() || *iter!=7) {
+ std::cerr<<"Insertion failed.! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ++ret;
+ }
+
+ if(*(alist.begin())!=5) {
+ std::cerr<<"Insert after at onebeforeBegin did not change head! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ++ret;
+ }
+ iter = alist.endModify();
+
+ if(iter!=alist.end()) {
+ std::cerr <<" Iterator got by endModify does not equal that got by end()! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ++ret;
+ }
+
+
+ iter.insert(20);
+
+ if(iter != alist.end()) {
+ std::cerr<<"Insertion changed end iterator! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ++ret;
+ }
+
+ if(tail(alist)!=20) {
+ std::cerr<<"tail was not changed!! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ++ret;
+ }
+
+ alist.clear();
+ iter=alist.beginModify();
+ iter.insert(5);
+ if(iter!=alist.end()) {
+ std::cerr<<"Insertion failed! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ++ret;
+ }
+ return ret;
+}
+
+int testPushPop(){
+ using namespace Dune;
+ int ret=0;
+
+ Dune::SLList<int,IntAllocator> alist;
+ //std::cout<<"PushPop 1:"<<alist<<std::endl;
+
+ if(alist.begin() != alist.end()) {
+ ret++;
+ std::cerr<<"For empty list begin and end iterator do not match! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ret++;
+ }
+
+ alist.push_back(1);
+
+ //std::cout<<"Push back 1: "<<alist<<std::endl;
+
+ if(*(alist.begin())!=1) {
+ std::cerr<<"Entry should be 1! Push back failed! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ ret++;
+ }
+
+ alist.push_back(2);
+
+ //std::cout<<"Push back 2: "<<alist<<std::endl;
+
+ if(*(alist.begin())!=1) {
+ ret++;
+ std::cerr<<"Entry should be 2! Push back failed! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ }
+
+ alist.push_front(3);
+ //std::cout<<"Push front 3: "<<alist<<std::endl;
+
+ if(*(alist.begin())!=3) {
+ ret++;
+ std::cerr<<"Entry should be 3! Push front failed! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ }
+
+ alist.pop_front();
+ //std::cout<<*(alist.begin())<<" Pop front: "<<alist<<std::endl;
+
+
+ if(*(alist.begin())!=1) {
+ ret++;
+ std::cerr<<"Entry should be 1, but is "<<*(alist.begin())<<"! Push back failed! "<<__FILE__<<":"<<__LINE__<<std::endl;
+ }
+ return ret;
+}
+
+int main()
+{
+ int ret=0;
+
+ //Dune::SLList<double> list;
+ Dune::SLList<double,DoubleAllocator> list, list1;
+ Dune::SLList<DoubleWrapper, DoubleWAllocator> list2;
+
+ randomizeListBack(list1);
+ randomizeListFront(list);
+
+ Dune::SLList<double,DoubleAllocator> copied(list);
+ if(copied.size()!=list.size()) {
+ std::cerr << "Size of copied list does not match!"<<std::endl;
+ ++ret;
+ }
+ else{
+ typedef Dune::SLList<double,DoubleAllocator>::const_iterator Iterator;
+ Iterator iend = list.end();
+ for(Iterator iter1=list.begin(), iter2=copied.begin(); iter1 != iend; ++iter1, ++iter2)
+ if(*iter1!=*iter2) {
+ std::cerr << "Entries of copied are not the same!"<<std::endl;
+ ++ret;
+ }
+ }
+
+ randomizeListFront(list2);
+
+ Printer<std::iterator_traits<Dune::SLList<double,DoubleAllocator>::ModifyIterator>::value_type> print;
+
+ Dune::SLList<double,DoubleAllocator>::ModifyIterator lbegin = list.beginModify(), lend = list.endModify();
+
+ double& d = lbegin.dereference();
+
+ d=2.0;
+
+ double& d1 = lbegin.dereference();
+
+ d1=3.0;
+
+ lbegin.dereference()=5.0;
+
+ lbegin.operator*()=5.0;
+
+ *lbegin=5.0;
+
+ std::cout << "Testing ConstIterator "<<std::endl;
+ ret+=testConstIterator(lbegin, lend, print);
+ std::cout << "Testing Iterator "<<std::endl;
+ ret+=testIterator(list);
+ std::cout << "Testing Iterator "<<std::endl;
+ ret+=testIterator(list1);
+
+ std::cout<< " Test PushPop "<<std::endl;
+ ret+=testPushPop();
+ std::cout<<" Test OneBeforeBegin"<<std::endl;
+
+ //ret+=testOneBeforeBegin(list1);
+
+ std::cout<< "test empty"<<std::endl;
+ ret+=testEmpty();
+ std::cout<< "test insert"<<std::endl;
+
+ ret+=testInsert();
+ std::cout<< "test delete"<<std::endl;
+ ret+=testDelete();
+
+ ret+=testAssign();
+ list.clear();
+ list1.clear();
+ list2.clear();
+ std::cout<<" randomize back"<<std::endl;
+ randomizeListBack(list);
+ std::cout<<" randomize front"<<std::endl;
+ randomizeListFront(list1);
+ return ret;
+}
--- /dev/null
+// -*- 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 <dune/common/static_assert.hh>
+
+int main()
+{
+ dune_static_assert(true, "OK");
+ return 0;
+}
--- /dev/null
+// -*- 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 <dune/common/static_assert.hh>
+
+int main()
+{
+ dune_static_assert(false, "FAIL");
+ return 0;
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// $Id$
+
+/*
+
+ Test to check if the standard streams in libdune can be properly
+ linked with this program and if they work
+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <fstream>
+
+#include <dune/common/stdstreams.hh>
+
+// enums are a nice special case (was a bug)
+enum check { VALUE = 5 };
+
+int main () {
+ try {
+ // let output happen but vanish
+ std::ofstream dummy("/dev/null");
+ Dune::derr.attach(dummy);
+
+ Dune::derr.push(true);
+ Dune::derr << "Teststring" << std::endl;
+
+ Dune::derr << VALUE << std::endl;
+ Dune::dverb << VALUE << std::endl;
+ Dune::dvverb << VALUE << std::endl;
+ Dune::dinfo << VALUE << std::endl;
+ Dune::dwarn << VALUE << std::endl;
+ Dune::dgrave << VALUE << std::endl;
+
+ // instantiate private stream and connect global stream
+ {
+ Dune::DebugStream<> mystream(dummy);
+ Dune::derr.tie(mystream);
+ Dune::derr << "Blah" << std::endl;
+ // untie before mystream gets destructed
+ Dune::derr.untie();
+ }
+
+ Dune::derr << "Still working" << std::endl;
+ } catch (Dune::Exception &e) {
+ std::cerr << e << std::endl;
+ return 2;
+ } catch (...) {
+ return 1;
+ };
+
+ return 0;
+}
--- /dev/null
+// -*- 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
+
+// #define DEBUG_ALLOCATOR_KEEP 1
+#define DEBUG_NEW_DELETE 3
+
+#include <dune/common/debugallocator.hh>
+
+#include <iostream>
+#include <cstdlib>
+#include <vector>
+
+class A
+{
+public:
+ A() { std::cout << "INIT A\n"; }
+ int x;
+ void foo() {};
+};
+
+void basic_tests ()
+{
+ using Dune::DebugMemory::alloc_man;
+
+ size_t s = 256;
+ double * x = alloc_man.allocate<double>(s);
+ x[s-1] = 10;
+
+ // access out of bounds
+#ifdef FAILURE1
+ x[s+1] = 1;
+#endif
+
+ // lost allocation, free and double-free
+#ifndef FAILURE2
+ alloc_man.deallocate<double>(x);
+#endif
+#ifdef FAILURE3
+ alloc_man.deallocate<double>(x);
+#endif
+
+ // access after free
+#ifdef FAILURE4
+ x[s-1] = 10;
+#endif
+}
+
+void allocator_tests()
+{
+ std::vector<double, Dune::DebugAllocator<double> > v;
+ v.push_back(10);
+ v.push_back(12);
+ v.size();
+ std::cout << v[0] << "\n";
+ std::cout << v[1] << "\n";
+#ifdef FAILURE5
+ std::cout << v[v.capacity()] << "\n";
+#endif
+}
+
+void new_delete_tests()
+{
+ std::cout << "alloc double[3]\n";
+ double * y = new double[3];
+ delete[] y;
+
+ std::cout << "alloc A[2]\n";
+ A * z = new A[2];
+ z->foo();
+ delete[] z;
+ z = 0;
+
+ std::cout << "alloc (buf) A[3]\n";
+ char * buf = (char*)malloc(128);
+ A * z2 = new (buf) A[3];
+ z2->foo();
+ free(buf);
+ z2 = 0;
+
+ std::cout << "alloc A[4]\n";
+ A * z4 = ::new A[4];
+ z4->foo();
+ ::delete[] z4;
+ z4 = 0;
+}
+
+int main(int, char**)
+{
+ basic_tests();
+ allocator_tests();
+ new_delete_tests();
+ return 0;
+}
--- /dev/null
+// -*- 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/fvector.hh>
+#include <dune/common/fassign.hh>
+
+using Dune::zero;
+using Dune::nextRow;
+
+template<class T> struct Print {};
+
+template<int s>
+struct Print< Dune::FieldVector<int,s> >
+{
+ static void print(Dune::FieldVector<int,s> & v)
+ {
+ for (int i=0; i<s; i++)
+ std::cout << "value[" << i << "] = " << v[i] << "\n";
+ }
+};
+
+template<int n, int m>
+struct Print< Dune::FieldMatrix<int,n,m> >
+{
+ static void print(Dune::FieldMatrix<int,n,m> & A)
+ {
+ for (int i=0; i<n; i++)
+ for (int j=0; j<m; j++)
+ std::cout << "value[" << i << "][" << j << "] = " << A[i][j] << "\n";
+ }
+};
+
+template<class T>
+void print(T & t) {
+ Print<T>::print(t);
+}
+
+int main ()
+{
+ try
+ {
+#ifdef _DUNE_TEST_M
+ Dune::FieldMatrix<int,_DUNE_TEST_N,_DUNE_TEST_M> x;
+#else
+ Dune::FieldVector<int,_DUNE_TEST_N> x;
+#endif
+
+ x <<= _VALUES;
+ print(x);
+
+ return 0;
+ }
+ catch (Dune::MathError &e)
+ {
+ std::cerr << "Dune reported MathError: " << e << std::endl;
+ return 1;
+ }
+ catch (Dune::Exception &e)
+ {
+ std::cerr << "Dune reported error: " << e << std::endl;
+ return 1;
+ }
+ catch (...)
+ {
+ std::cerr << "Unknown exception thrown!" << std::endl;
+ return 1;
+ }
+}
--- /dev/null
+// -*- 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 <dune/common/fassign.hh>
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#include <config.h>
+
+#include <iostream>
+#include <dune/common/fvector.hh>
+#include <dune/common/fassign.hh>
+
+using namespace Dune;
+
+int main(int, char**) {
+ Dune::FieldVector<double,3> pos;
+
+ pos <<= 1, 0, 0;
+
+ Dune::FieldVector<float,FVSIZE> pos2(pos);
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// Test the new (Dune) interface of float_cmp
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <iostream>
+
+#include <dune/common/float_cmp.hh>
+
+using std::cout;
+using std::endl;
+using std::flush;
+
+/////////////////////////
+//
+// compile time checks
+//
+
+// check that we can access the functions as FloatCmp::function from within the Dune namespace
+namespace Dune {
+ void checkNamespaceAccess() {
+ FloatCmp::eq(0.0, 0.0);
+ }
+} // namespace Dune
+ // check that we can access the functions as FloatCmp::function with using namespace Dune
+void checkUsingAccess() {
+ using namespace Dune;
+ FloatCmp::eq(0.0, 0.0);
+}
+
+// run time checks
+const char* repr(bool b) {
+ if(b) return "true ";
+ else return "false";
+}
+
+int passed = 0;
+int failed = 0;
+
+void count(bool pass) {
+ if(pass) { cout << "passed"; ++passed; }
+ else { cout << "failed"; ++failed; }
+}
+
+template<typename F>
+void tests(F f1, F f2, typename Dune::FloatCmp::EpsilonType<F>::Type eps, bool inside)
+{
+ bool result;
+
+ cout << "eq(" << f1 << ", " << f2 << ", " << eps << ") = " << flush;
+ result = Dune::FloatCmp::eq(f1, f2, eps);
+ cout << repr(result) << "\t";
+ count(result == inside);
+ cout << endl;
+
+ cout << "ge(" << f1 << ", " << f2 << ", " << eps << ") = " << flush;
+ result = Dune::FloatCmp::ge(f1, f2, eps);
+ cout << repr(result) << "\t";
+ count(result == (inside || f1 > f2));
+ cout << endl;
+
+ cout << "le(" << f1 << ", " << f2 << ", " << eps << ") = " << flush;
+ result = Dune::FloatCmp::le(f1, f2, eps);
+ cout << repr(result) << "\t";
+ count(result == (inside || f1 < f2));
+ cout << endl;
+
+ cout << "ne(" << f1 << ", " << f2 << ", " << eps << ") = " << flush;
+ result = Dune::FloatCmp::ne(f1, f2, eps);
+ cout << repr(result) << "\t";
+ count(result == !inside);
+ cout << endl;
+
+ cout << "gt(" << f1 << ", " << f2 << ", " << eps << ") = " << flush;
+ result = Dune::FloatCmp::gt(f1, f2, eps);
+ cout << repr(result) << "\t";
+ count(result == (!inside && f1 > f2));
+ cout << endl;
+
+ cout << "lt(" << f1 << ", " << f2 << ", " << eps << ") = " << flush;
+ result = Dune::FloatCmp::lt(f1, f2, eps);
+ cout << repr(result) << "\t";
+ count(result == (!inside && f1 < f2));
+ cout << endl;
+}
+
+template<typename F>
+void tests(F f1, F f2, const typename Dune::FloatCmpOps<F> &ops, bool inside)
+{
+ bool result;
+ cout << "ops = operations(" << ops.epsilon() << ")" << endl;
+
+ cout << "ops.eq(" << f1 << ", " << f2 << ") = " << flush;
+ result = ops.eq(f1, f2);
+ cout << repr(result) << "\t";
+ count(result == inside);
+ cout << endl;
+
+ cout << "ops.ge(" << f1 << ", " << f2 << ") = " << flush;
+ result = ops.ge(f1, f2);
+ cout << repr(result) << "\t";
+ count(result == (inside || f1 > f2));
+ cout << endl;
+
+ cout << "ops.le(" << f1 << ", " << f2 << ") = " << flush;
+ result = ops.le(f1, f2);
+ cout << repr(result) << "\t";
+ count(result == (inside || f1 < f2));
+ cout << endl;
+
+ cout << "ops.ne(" << f1 << ", " << f2 << ") = " << flush;
+ result = ops.ne(f1, f2);
+ cout << repr(result) << "\t";
+ count(result == !inside);
+ cout << endl;
+
+ cout << "ops.gt(" << f1 << ", " << f2 << ") = " << flush;
+ result = ops.gt(f1, f2);
+ cout << repr(result) << "\t";
+ count(result == (!inside && f1 > f2));
+ cout << endl;
+
+ cout << "ops.lt(" << f1 << ", " << f2 << ") = " << flush;
+ result = ops.lt(f1, f2);
+ cout << repr(result) << "\t";
+ count(result == (!inside && f1 < f2));
+ cout << endl;
+}
+
+int main() {
+ cout.setf(std::ios_base::scientific, std::ios_base::floatfield);
+ cout.precision(16);
+ Dune::FloatCmpOps<double> ops(1e-7);
+
+ cout << "Tests inside the epsilon environment" << endl;
+ tests<double>(1.0, 1.00000001, 1e-7, true);
+ tests<double>(1.0, 1.00000001, ops, true);
+
+ cout << "Tests outside the epsilon environment, f1 < f2" << endl;
+ tests<double>(1.0, 1.000001, 1e-7, false);
+ tests<double>(1.0, 1.000001, ops, false);
+
+ cout << "Tests outside the epsilon environment, f1 > f2" << endl;
+ tests<double>(1.000001, 1.0, 1e-7, false);
+ tests<double>(1.000001, 1.0, ops, false);
+
+ cout << "Tests with f1 = f2 = 0" << endl;
+ tests<double>(0, 0, 1e-7, true);
+ tests<double>(0, 0, ops, true);
+
+ int total = passed + failed;
+ cout << passed << "/" << total << " tests passed; " << failed << "/" << total << " tests failed" << endl;
+ if(failed > 0) return 1;
+ else return 0;
+}
--- /dev/null
+// -*- 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 <fstream>
+#include <dune/common/fvector.hh>
+#include <dune/common/timer.hh>
+#include <dune/istl/bvector.hh>
+#include <dune/common/iteratorfacades.hh>
+
+template<int bs, int sz>
+void timing_vector()
+{
+ std::cout << "timing_vector<" << bs << ", " << sz << ">\n";
+ typedef Dune::FieldVector<double,bs> VB;
+ typedef Dune::BlockVector<VB> BV;
+ typedef Dune::BlockVector<BV> BBV;
+ BV bv1(sz), bv2(sz);
+ BV bv3(sz), bv4(sz);
+ bv1 = 1;
+ bv2 = 0;
+ bv2[1][0]=1;
+ bv2[1][1]=2;
+
+ bv3 = 0;
+ bv4 = 0;
+
+ BBV bbv(2);
+ bbv[0].resize(bv1.N());
+ bbv[1].resize(bv2.N());
+
+ BBV bbv2(2);
+#warning deep copy is broken!
+ /* bbv2 = bbv2; */
+ bbv2[0] = bv3;
+ bbv2[1] = bv4;
+ // bbv2 = 0;
+
+ Dune::Timer stopwatch;
+ stopwatch.reset();
+ for (int i=0; i<10; i++)
+ {
+#ifdef DUNE_EXPRESSIONTEMPLATES
+#ifdef DUNE_FLATIT
+ for (int a=0; a<2; a++)
+ for (int b=0; b<sz; b++)
+ for (int c=0; c<bs; c++)
+ bbv2[a][b][c] += 2*bbv[a][b][c];
+#else
+ bbv2 += 2*bbv;
+#endif
+#else
+ bbv2.axpy(2,bbv);
+#endif
+ }
+ std::cout << "Time [bbv2.axpy(2,bbv)] " << stopwatch.elapsed() << std::endl;
+}
+
+#if 0
+//template<int BlockSize, int N, int M>
+template<int BN, int BM, int N, int M>
+void timing_matrix()
+{
+ std::cout << "timing_matrix<" << BN << ", " << BM << ", "
+ << N << ", " << M << ">\n";
+
+ typedef double matvec_t;
+ typedef Dune::FieldVector<matvec_t,BN> LVB;
+ typedef Dune::FieldVector<matvec_t,BM> VB;
+ typedef Dune::FieldMatrix<matvec_t,BN,BM> MB;
+ typedef Dune::BlockVector<LVB> LeftVector;
+ typedef Dune::BlockVector<VB> Vector;
+ typedef Dune::BCRSMatrix<MB> Matrix;
+
+ Matrix A(N,M,Matrix::row_wise);
+ typename Matrix::CreateIterator i=A.createbegin();
+ typename Matrix::CreateIterator end=A.createend();
+ std::cout << "Building matrix structure\n";
+ // build up the matrix structure
+ int c=0;
+ for (; i!=end; ++i)
+ {
+ // insert a non zero entry for myself
+ i.insert(c);
+ // insert index M-1
+ i.insert(M-1);
+ c++;
+ }
+ std::cout << "...done\n";
+
+ LeftVector v(N);
+ v = 0;
+ Vector x(M);
+ x = 1;
+
+ Dune::Timer stopwatch;
+ stopwatch.reset();
+#ifdef DUNE_EXPRESSIONTEMPLATES
+ v += A * x;
+#else
+ A.umv(x,v);
+#endif
+ std::cout << "Time [v+=A*x] " << stopwatch.elapsed() << std::endl;
+
+ std::cout << std::endl;
+}
+#endif
+
+int main ()
+{
+#ifdef DUNE_EXPRESSIONTEMPLATES
+#ifdef DUNE_FLATIT
+ std::cout << "Handwritten loops\n";
+#else
+ std::cout << "Expression Templates\n";
+#endif
+#else
+ std::cout << "Template Meta Program\n";
+#endif
+
+ timing_vector<1,1000000>();
+ timing_vector<2,500000>();
+ timing_vector<10,100000>();
+ timing_vector<40,25000>();
+ timing_vector<100,10000>();
+ timing_vector<400,2500>();
+
+ // timing_matrix<150,150,500,4000>();
+ // timing_matrix<150,150,1000,2000>();
+ // timing_matrix<1,18,400000,500000>();
+ // timing_matrix<6,3,400000,500000>();
+ // timing_matrix<3,6,400000,500000>();
+ // timing_matrix<18,1,400000,500000>();
+ // timing_matrix<50,50,9000,10000>();
+
+ std::cout << std::endl;
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+
+// $Id$
+
+// make sure assert works even when not compiling for debugging
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(DISABLE_TR1_TUPLE) && defined(HAVE_TR1_TUPLE)
+#undef HAVE_TR1_TUPLE
+#endif
+
+#if defined(DISABLE_STD_TUPLE) && defined(HAVE_TUPLE)
+#undef HAVE_TUPLE
+#endif
+
+#include <cassert>
+#include <cstdlib>
+#include <iostream>
+#include <ostream>
+#include <string>
+#include <vector>
+
+#include <dune/common/classname.hh>
+#include <dune/common/tuples.hh>
+
+using namespace Dune;
+
+template<class T>
+void test(T& tuple)
+{
+ float f DUNE_UNUSED;
+ f = get<0>(tuple);
+ int i DUNE_UNUSED;
+ i = get<1>(tuple);
+ double d DUNE_UNUSED;
+ d = get<2>(tuple);
+ char c DUNE_UNUSED;
+ c = get<3>(tuple);
+ std::string s;
+ s = get<4>(tuple);
+ typename tuple_element<4,typename remove_const<T>::type>::type s2 = get<4>(tuple);
+}
+
+int iteratorTupleTest()
+{
+ std::vector<int> v;
+
+ v.push_back(0);
+ v.push_back(1);
+ v.push_back(2);
+
+ typedef std::vector<int>::iterator iterator;
+ typedef std::vector<int>::const_iterator const_iterator;
+ typedef tuple<iterator,const_iterator, const_iterator> Tuple;
+
+
+ Tuple tuple_(v.begin(), v.begin(), v.end());
+ dune_static_assert(tuple_size<Tuple>::value==3, "The tuple size should be 3!");;
+
+ int ret=0;
+
+ if(get<0>(tuple_)!= v.begin()) {
+ std::cerr<<"Iterator tuple construction failed!"<<std::endl;
+ ret++;
+ }
+ assert(get<1>(tuple_) == v.begin());
+ assert(get<1>(tuple_) == get<0>(tuple_));
+ if(get<2>(tuple_)!= v.end()) {
+ std::cerr<<"Iterator tuple construction failed!"<<std::endl;
+ ret++;
+ }
+
+ assert(get<2>(tuple_) == v.end());
+ assert(get<0>(tuple_) != v.end());
+ assert(get<1>(tuple_) != get<2>(tuple_));
+ return ret;
+}
+
+int lessTest()
+{
+ tuple<int,float,double> t1(1,2.0,3.0);
+ tuple<int,int,int> t2(1,2,1);
+
+ int ret=0;
+
+ if ((t1<t2) != false) ret++;
+ std::cout << "[" << t1 << "] < [" << t2 << "] = " << (t1<t2) << std::endl;
+ if ((t2<t1) != true) ret++;
+ std::cout << "[" << t2 << "] < [" << t1 << "] = " << (t2<t1) << std::endl;
+
+ // This would result in a compiler error
+ // Tuple<int,int> t3(1,2);
+ // std::cout << "[" << t3 << "] < [" << t1 << "] = " << (t3<t1) << std::endl;
+
+ return ret;
+}
+
+int copyTest()
+{
+ tuple<float,int,double,char,std::string> tuple_, tuple1(3.0,1,3.3,'c',std::string("hallo")), tuple2(tuple1);
+
+ std::cout<<tuple1<<std::endl;
+ std::cout<<tuple2<<std::endl;
+ tuple_=tuple1;
+ std::cout<<tuple_<<std::endl;
+
+ if(tuple_!=tuple1)
+ return 1;
+ if(tuple2!=tuple1)
+ return 1;
+
+ return 0;
+}
+
+int referenceTest()
+{
+ // make sure const tuples of references have assignable members, as long as
+ // the member references a non-const type
+ {
+ int n = 0;
+ const tuple<int&> t(n);
+ get<0>(t) = 777;
+ assert(n == 777);
+ }
+
+ int k=5;
+ int& kr(k);
+ kr=20;
+ int i=50;
+ double d=-3.3;
+ long j=-666;
+ tuple<int,double,long> t1(100, 5.0, 10);
+ tuple<int,int,int> t2(1,5,9);
+ std::cout << "i="<<i<<" d="<<d<<" j="<<j<<std::endl;
+
+ tuple<int&,double&,long&> tr(i,d,j);
+
+ get<0>(tr)=3;
+ assert(get<0>(tr)==3);
+
+ std::cout <<"tr="<< tr<<std::endl;
+
+ tuple<int> i1(5);
+ tuple<int&> ir(i);
+ ir=i1;
+
+ t1=t2;
+
+ std::cout <<"tr="<< tr<<std::endl;
+ std::cout <<"t1="<< t1<<std::endl;
+ tr=t1;
+
+ if(tr!=t1)
+ return 1;
+ else
+ std::cout<<"t1="<<t1<< " tr="<<tr<<std::endl;
+
+
+ return 0;
+}
+
+int pointerTest()
+{
+ int k=5, k1=6;
+ int i=50;
+ double d=-3.3, d1=7.8;
+ long j=-666, j1=-300;
+ tuple<int*,double*,long*> t1(&k, &d, &j);
+ tuple<int*,double*,long*> t2(&k1,&d1,&j1);
+ std::cout << "i="<<i<<" d="<<d<<" j="<<j<<std::endl;
+
+ tuple<int*,double*,long*> tr(&i,&d,&j);
+
+ *get<0>(tr)=3;
+ assert(*get<0>(tr)==3);
+
+ std::cout <<"tr="<< tr<<std::endl;
+
+ tuple<int> i1(5);
+ tuple<int*> ir(&i);
+
+ t2=t1;
+
+ std::cout <<"tr="<< tr<<std::endl;
+ std::cout <<"t1="<< t1<<std::endl;
+ tr=t1;
+
+ if(tr!=t1)
+ return 1;
+ else
+ std::cout<<"t1="<<t1<< " tr="<<tr<<std::endl;
+
+
+ return 0;
+}
+
+int constPointerTest()
+{
+ int k=5, k1=88;
+ int i=50;
+ double d=-3.3, d1=6.8;
+ long j=-666, j1=-500;
+ tuple<const int*, const double*, const long*> t1(&k, &d, &j);
+ tuple<int*, double*, long*> t2(&k1,&d1,&j1);
+ std::cout << "i="<<i<<" d="<<d<<" j="<<j<<std::endl;
+
+ tuple<const int*, const double*, const long*> tr(&i,&d,&j);
+
+ std::cout << *get<0>(tr)<<std::endl;
+
+ std::cout <<"tr="<< tr<<std::endl;
+
+ tuple<int> i1(5);
+ tuple<const int*> ir(&i);
+
+ t1=t2;
+
+ std::cout <<"tr="<< tr<<std::endl;
+ std::cout <<"t1="<< t1<<std::endl;
+ tr=t1;
+
+ if(tr!=t1)
+ return 1;
+ else
+ std::cout<<"t1="<<t1<< " tr="<<tr<<std::endl;
+
+
+ return 0;
+}
+
+int tuple_tr1_test()
+{
+ int ret=0;
+
+ tuple<int,double> t(1,3.14);
+ int sz = tuple_size<tuple<int, double, char> >::value;
+ if(sz!=3) ++ret;
+
+ // contruct a tuple
+
+ t= make_tuple(5, 10.9);
+
+
+ // get the second element
+ tuple_element<1,tuple<int,double> >::type d DUNE_UNUSED;
+ d=get<1>(t);
+
+ get<0>(t)=16;
+
+ std::cout<<t<<std::endl;
+
+ return ret;
+}
+
+
+int main(int, char**)
+{
+ tuple<float,int,double,char,std::string> tuple_;
+ std::cout << "=== testing tuple: " << className(tuple_) << std::endl;
+
+ test(tuple_);
+ test(static_cast<tuple<float,int,double,char,std::string>& >(tuple_));
+ test(static_cast<const tuple<float,int,double,char,std::string>&>(tuple_));
+ return (copyTest()+iteratorTupleTest()+referenceTest()+lessTest()
+ +pointerTest()+constPointerTest()+tuple_tr1_test());
+
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <cstddef>
+
+#include <dune/common/static_assert.hh>
+#include <dune/common/tuples.hh>
+#include <dune/common/tupleutility.hh>
+
+//////////////////////////////////////////////////////////////////////
+//
+// check FirstTypeIndex
+//
+typedef Dune::tuple<int, unsigned, double> MyTuple;
+dune_static_assert((Dune::FirstTypeIndex<MyTuple, int>::value == 0),
+ "FirstTypeIndex finds the wrong index for double in "
+ "MyTuple!");
+dune_static_assert((Dune::FirstTypeIndex<MyTuple, unsigned>::value == 1),
+ "FirstTypeIndex finds the wrong index for double in "
+ "MyTuple!");
+dune_static_assert((Dune::FirstTypeIndex<MyTuple, double>::value == 2),
+ "FirstTypeIndex finds the wrong index for double in "
+ "MyTuple!");
+
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// check PushBackTuple
+typedef Dune::PushBackTuple<MyTuple, char>::type MyTupleAppended1;
+typedef Dune::tuple<int, unsigned, double, char> MyTupleAppended2;
+dune_static_assert((Dune::is_same<MyTupleAppended1, MyTupleAppended2>::value),
+ "PushBackTuple failed!");
+
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// check PushFrontTuple
+typedef Dune::PushFrontTuple<MyTuple, char>::type MyTuplePrepended1;
+typedef Dune::tuple<char, int, unsigned, double> MyTuplePrepended2;
+dune_static_assert((Dune::is_same<MyTuplePrepended1, MyTuplePrepended2>::value),
+ "PushFrontTuple failed!");
+
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// check JoinTuples
+typedef Dune::JoinTuples<MyTuple, MyTuple>::type MyTupleMyTuple1;
+typedef Dune::tuple<int, unsigned, double, int, unsigned, double> MyTupleMyTuple2;
+dune_static_assert((Dune::is_same<MyTupleMyTuple1, MyTupleMyTuple2>::value),
+ "JoinTuples failed!");
+
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// check FlattenTuple
+typedef Dune::tuple<char, float> MyTuple2;
+typedef Dune::tuple<MyTuple, MyTuple2> MyTupleTuple;
+typedef Dune::FlattenTuple<MyTupleTuple>::type MyTupleTupleFlat1;
+typedef Dune::tuple<int, unsigned, double, char, float> MyTupleTupleFlat2;
+dune_static_assert((Dune::is_same<MyTupleTupleFlat1, MyTupleTupleFlat2>::value),
+ "FlattenTuples failed!");
+
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// check nested ReduceTuple with a litte TMP
+
+// A tuple of a range of integers wrapped in integral_constant types
+template<int start, int end>
+struct Range
+{
+ typedef typename Dune::PushBackTuple<
+ typename Range<start, end-1>::type,
+ typename Dune::integral_constant<int,end-1>
+ >::type type;
+};
+
+template<int start>
+struct Range<start, start>
+{
+ typedef Dune::tuple<> type;
+};
+
+// An accumulator to build up a list of divisors of an integer using reduce
+template<class Data, class PotentialDivisor>
+struct DivisorAccumulator
+{
+ enum {value = Data::first_type::value};
+ enum {isDivisor = (PotentialDivisor::value*(value / PotentialDivisor::value)==value)};
+
+ typedef typename Data::second_type OldTuple;
+ typedef typename Dune::PushBackTuple<OldTuple, PotentialDivisor>::type ExtendedTuple;
+ typedef typename Dune::conditional<isDivisor, ExtendedTuple, OldTuple>::type NewTuple;
+
+ typedef typename std::pair<typename Data::first_type, NewTuple> type;
+};
+
+// Construct list of divisors using reduce
+template<int X>
+struct Divisors
+{
+ typedef typename Dune::ReduceTuple<
+ DivisorAccumulator,
+ typename Range<1,X+1>::type,
+ typename std::pair<typename Dune::integral_constant<int, X>, typename Dune::tuple<> >
+ >::type::second_type type;
+
+ enum {value = Dune::tuple_size<type>::value};
+};
+
+// An accumulator to build up a list of primes up to a fixed integer
+template<class Data, class N>
+struct PrimeAccumulator
+{
+ enum {isPrime = (Divisors<N::value>::value==2)};
+
+ typedef typename Dune::conditional<isPrime, typename Dune::PushBackTuple<Data, N>::type, Data>::type type;
+};
+
+// Construct list primes
+template<int X>
+struct Primes
+{
+ typedef typename Dune::ReduceTuple<
+ PrimeAccumulator,
+ typename Range<1,X+1>::type,
+ typename Dune::tuple<>
+ >::type type;
+};
+
+typedef Primes<9>::type Primes1;
+typedef Dune::tuple<
+ Dune::integral_constant<int, 2>,
+ Dune::integral_constant<int, 3>,
+ Dune::integral_constant<int, 5>,
+ Dune::integral_constant<int, 7> > Primes2;
+dune_static_assert((Dune::is_same<Primes1, Primes2>::value),
+ "ReduceTuple failed in primes-tmp!");
+
+
+int main() {}
--- /dev/null
+// -*- 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
+
+/** \file
+ * \brief Test the TypeTraits class
+ */
+
+#include <iostream>
+#include <cassert>
+
+#include <dune/common/typetraits.hh>
+
+int main() {
+
+ // Test TypeTraits::isPointer
+ assert( not Dune::TypeTraits<int>::isPointer );
+ assert( Dune::TypeTraits<int*>::isPointer );
+ assert( Dune::TypeTraits<int**>::isPointer );
+ assert( Dune::TypeTraits<int(*)(int)>::isPointer );
+
+ // Test TypeTraits::isReference
+ assert( not Dune::TypeTraits<int>::isReference );
+ assert( Dune::TypeTraits<int&>::isReference );
+#if HAVE_RVALUE_REFERENCES
+ assert( not Dune::TypeTraits<int&&>::isReference );
+#endif
+
+ // Test TypeTraits::PointeeType
+ assert( (Dune::is_same<Dune::Empty, Dune::TypeTraits<int>::PointeeType>::value) );
+ assert( (Dune::is_same<int, Dune::TypeTraits<int*>::PointeeType>::value) );
+ assert( (Dune::is_same<int*, Dune::TypeTraits<int**>::PointeeType>::value) );
+ assert( (Dune::is_same<const int, Dune::TypeTraits<const int*>::PointeeType>::value) );
+ assert( (Dune::is_same<Dune::Empty, Dune::TypeTraits<int* const>::PointeeType>::value) );
+
+ // Test TypeTraits::ReferredType
+ assert( (Dune::is_same<int, Dune::TypeTraits<int>::ReferredType>::value) );
+ assert( (Dune::is_same<int, Dune::TypeTraits<int&>::ReferredType>::value) );
+
+ // Test is_pointer
+ assert( not Dune::is_pointer<int>::value );
+ assert( Dune::is_pointer<int*>::value );
+ assert( Dune::is_pointer<int**>::value );
+ assert( Dune::is_pointer<int(*)(int)>::value );
+
+ // Test is_reference
+ assert( not Dune::is_lvalue_reference<int>::value );
+ assert( Dune::is_lvalue_reference<int&>::value );
+#if HAVE_RVALUE_REFERENCES
+ assert( not Dune::is_lvalue_reference<int&&>::value );
+#endif
+
+ // Test remove_pointer
+ // Note: when the argument T is not a pointer, TypeTraits::PointeeType returns Dune::Empty,
+ // while Dune::remove_pointer (as std::remove_pointer), returns T itself
+ assert( (Dune::is_same<int, Dune::remove_pointer<int>::type>::value) );
+ assert( (Dune::is_same<int, Dune::remove_pointer<int*>::type>::value) );
+ assert( (Dune::is_same<int*, Dune::remove_pointer<int**>::type>::value) );
+ assert( (Dune::is_same<const int, Dune::remove_pointer<const int*>::type>::value) );
+ assert( (Dune::is_same<int, Dune::remove_pointer<int* const>::type>::value) );
+
+ // Test remove_reference
+ assert( (Dune::is_same<int, Dune::remove_reference<int>::type>::value) );
+ assert( (Dune::is_same<int, Dune::remove_reference<int&>::type>::value) );
+#if HAVE_RVALUE_REFERENCES
+ assert( (Dune::is_same<int, Dune::remove_reference<int&&>::type>::value) );
+#endif
+
+ return 0;
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <dune/common/static_assert.hh>
+#include <dune/common/tuples.hh>
+#include <dune/common/typetraits.hh>
+#include <dune/common/tupleutility.hh>
+#include <iostream>
+
+template<class T>
+struct Eval
+{
+ typedef void* Type;
+};
+
+struct Counter {
+ Counter() : result_(0) {}
+
+ template <class T1>
+ void visit(T1) { ++result_; }
+
+ template <class T1, class T2>
+ void visit(T1, T2) { ++(++result_); }
+ int result_;
+};
+
+
+int main(int, char**)
+{
+
+ typedef Dune::tuple<int*,double*,long*,char*> PointerTuple;
+
+ Dune::tuple<int*,double*,long*,char*> pointers = Dune::NullPointerInitialiser<PointerTuple>::apply();
+ int ret=0;
+
+ if(Dune::get<0>(pointers)!=0) {
+ std::cerr<<"First pointer not null"<<std::endl;
+ ret=1;
+ }
+ if(Dune::get<1>(pointers)!=0) {
+ std::cerr<<"Second pointer not null"<<std::endl;
+ ret=2;
+ }
+
+ if(Dune::get<2>(pointers)!=0) {
+ std::cerr<<"Third pointer not null"<<std::endl;
+ ret=3;
+ }
+
+ if(Dune::get<3>(pointers)!=0) {
+ std::cerr<<"Fourth pointer not null"<<std::endl;
+ ret=4;
+ }
+
+ int i = 3;
+ long l = 4;
+ char c = 's';
+
+ typedef Dune::tuple<int&,char&,long&,char&> RefTuple1;
+ typedef Dune::tuple<int*,char*,long*,char*> PointerTuple1;
+ dune_static_assert((Dune::is_same<PointerTuple1,
+ Dune::ForEachType<Dune::AddPtrTypeEvaluator,
+ RefTuple1>::Type>::value),
+ "RefTuple1 with added pointers should be the same as "
+ "PointerTuple1, but it isn't!");
+
+ RefTuple1 refs(i, c, l, c);
+ PointerTuple1 pointers1
+ (Dune::transformTuple<Dune::AddPtrTypeEvaluator>(refs));
+ if(&i != Dune::get<0>(pointers1) || &c != Dune::get<1>(pointers1) ||
+ &l != Dune::get<2>(pointers1) || &c != Dune::get<3>(pointers1)) {
+ std::cerr << "utilitytest: error: incorrect pointers in pointers1"
+ << std::endl;
+ ret = 1;
+ }
+
+ if(static_cast<size_t>(Dune::tuple_size<PointerTuple>::value) != static_cast<size_t>(Dune::tuple_size<PointerTuple>::value)) {
+ std::cerr<<"Length and size do not match!"<<std::endl;
+ }
+
+ Counter count;
+ Dune::ForEachValue<PointerTuple> forEach(pointers);
+
+ forEach.apply(count);
+ std::cout << "Number of elements is: " << count.result_ << std::endl;
+
+
+
+ Dune::ForEachValuePair<PointerTuple,PointerTuple1> foreach1(pointers, pointers1);
+
+ foreach1.apply(count);
+
+ if(Dune::At<2>::get(pointers)!=Dune::get<1>(pointers)) {
+ ret+=10;
+ std::cerr<<"at inconsistent!"<<std::endl;
+ }
+
+ PointerTuple1 p(new int(), new char(), new long(), new char());
+
+ typedef Dune::ForEachType<Eval,PointerTuple1>::Type ConvertedType;
+ Dune::PointerPairDeletor<PointerTuple1>::apply(p);
+
+ return ret;
+}
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_TIMER_HH
+#define DUNE_TIMER_HH
+
+#ifndef TIMER_USE_STD_CLOCK
+// headers for std::chrono
+#include <chrono>
+#else
+// headers for std::clock
+#include <ctime>
+#endif
+
+// headers for stderror(3)
+#include <cstring>
+
+// access to errno in C++
+#include <cerrno>
+
+#include "exceptions.hh"
+
+namespace Dune {
+
+ /** @addtogroup Common
+ @{
+ */
+
+ /*! \file
+ \brief A simple timing class.
+ */
+
+ /** \brief %Exception thrown by the Timer class */
+ class TimerError : public SystemError {} ;
+
+
+ /** \brief A simple stop watch
+
+ This class reports the elapsed user-time, i.e. time spent computing,
+ after the last call to Timer::reset(). The results are seconds and
+ fractional seconds. Note that the resolution of the timing depends
+ on your OS kernel which should be somewhere in the milisecond range.
+
+ The class is basically a wrapper for the libc-function getrusage()
+
+ \warning In a multi-threading situation, this class does NOT return wall-time!
+ Instead, the run time for all threads will be added up.
+ For example, if you have four threads running in parallel taking one second each,
+ then the Timer class will return an elapsed time of four seconds.
+
+ */
+ class Timer
+ {
+ public:
+
+ /** \brief A new timer, create and reset
+ *
+ * \param startImmediately If true (default) the timer starts counting immediately
+ */
+ Timer (bool startImmediately=true) throw(TimerError)
+ {
+ isRunning_ = startImmediately;
+ reset();
+ }
+
+ //! Reset timer while keeping the running/stopped state
+ void reset() throw (TimerError)
+ {
+ sumElapsed_ = 0.0;
+ storedLastElapsed_ = 0.0;
+ rawReset();
+ }
+
+
+ //! Start the timer and continue measurement if it is not running. Otherwise do nothing.
+ void start() throw (TimerError)
+ {
+ if (not (isRunning_))
+ {
+ rawReset();
+ isRunning_ = true;
+ }
+ }
+
+
+ //! Get elapsed user-time from last reset until now/last stop in seconds.
+ double elapsed () const throw (TimerError)
+ {
+ // if timer is running add the time elapsed since last start to sum
+ if (isRunning_)
+ return sumElapsed_ + lastElapsed();
+
+ return sumElapsed_;
+ }
+
+
+ //! Get elapsed user-time from last start until now/last stop in seconds.
+ double lastElapsed () const throw (TimerError)
+ {
+ // if timer is running return the current value
+ if (isRunning_)
+ return rawElapsed();
+
+ // if timer is not running return stored value from last run
+ return storedLastElapsed_;
+ }
+
+
+ //! Stop the timer and return elapsed().
+ double stop() throw (TimerError)
+ {
+ if (isRunning_)
+ {
+ // update storedLastElapsed_ and sumElapsed_ and stop timer
+ storedLastElapsed_ = lastElapsed();
+ sumElapsed_ += storedLastElapsed_;
+ isRunning_ = false;
+ }
+ return elapsed();
+ }
+
+
+ private:
+
+ bool isRunning_;
+ double sumElapsed_;
+ double storedLastElapsed_;
+
+
+#ifdef TIMER_USE_STD_CLOCK
+ void rawReset() throw (TimerError)
+ {
+ cstart = std::clock();
+ }
+
+ double rawElapsed () const throw (TimerError)
+ {
+ return (std::clock()-cstart) / static_cast<double>(CLOCKS_PER_SEC);
+ }
+
+ std::clock_t cstart;
+#else
+ void rawReset() throw (TimerError)
+ {
+ cstart = std::chrono::high_resolution_clock::now();
+ }
+
+ double rawElapsed () const throw (TimerError)
+ {
+ std::chrono::high_resolution_clock::time_point now = std::chrono::high_resolution_clock::now();
+ std::chrono::duration<double> time_span = std::chrono::duration_cast<std::chrono::duration<double> >(now - cstart);
+ return time_span.count();
+ }
+
+ std::chrono::high_resolution_clock::time_point cstart;
+#endif
+ }; // end class Timer
+
+ /** @} end documentation */
+
+} // end namespace
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+
+#ifndef DUNE_TUPLES_HH
+#define DUNE_TUPLES_HH
+
+#include <iostream>
+
+#include "typetraits.hh"
+#include "static_assert.hh"
+#include "unused.hh"
+
+#ifdef HAVE_TUPLE
+#include <tuple>
+#elif defined HAVE_TR1_TUPLE
+#include <tr1/tuple>
+#endif
+
+namespace Dune {
+ /** @addtogroup Common
+ *
+ * @{
+ */
+ /**
+ * @file
+ * @brief Fallback implementation of the std::tuple class
+ *
+ * This a refined implementation of the approach defined in
+ * in the article "Tuples and multiple return values
+ * in C++" of Jaakko Järvi (Turku Centre of Computer
+ * Science, TUCS Technical Report No 249, March 1999,
+ * ISBN 952-12-0401-X, ISSN 1239-1891) available from the
+ * <a href="http://www.tucs.fi/publications/">TUCS publications archive</a>
+ * @author Markus Blatt
+ */
+
+
+ template<class T>
+ struct TupleAccessTraits
+ {
+ typedef typename ConstantVolatileTraits<T>::ConstType& ConstType;
+ typedef T& NonConstType;
+ typedef const typename ConstantVolatileTraits<T>::UnqualifiedType& ParameterType;
+ };
+
+ template<class T>
+ struct TupleAccessTraits<T*>
+ {
+ typedef typename ConstantVolatileTraits<T>::ConstType* ConstType;
+ typedef T* NonConstType;
+ typedef T* ParameterType;
+ };
+
+ template<class T>
+ struct TupleAccessTraits<T&>
+ {
+ typedef T& ConstType;
+ typedef T& NonConstType;
+ typedef T& ParameterType;
+ };
+
+#ifdef HAVE_TUPLE
+ using std::tuple;
+#elif defined HAVE_TR1_TUPLE
+ using std::tr1::tuple;
+#else
+ /**
+ * @brief An empty class.
+ */
+ struct Nil
+ {};
+
+ namespace
+ {
+ inline const Nil nullType()
+ {
+ return Nil();
+ }
+ }
+
+ /**
+ * @brief A tuple consisting of two objects.
+ *
+ * This is similar to std::pair
+ */
+ template<typename T1, typename TT>
+ struct Pair
+ {
+ /**
+ * @brief The type of the first field.
+ */
+ typedef T1 Type1;
+
+ /**
+ * @brief The type of the second field.
+ */
+ typedef TT Type2;
+ // enum{
+ // /**
+ // * @brief The number of values we hold.
+ // */
+ // values = 2;
+ // };
+
+ /**
+ * @brief Constructor
+ *
+ * @param t1 The value of the first field.
+ * @param t2 The value of the second field.
+ * @param t3 The value of the third field.
+ * @param t4 The value of the 4th field.
+ * @param t5 The value of the 5th field.
+ * @param t6 The value of the 6th field.
+ * @param t7 The value of the 7th field.
+ * @param t8 The value of the 8th field.
+ * @param t9 The value of the 9th field.
+ */
+ template<typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9>
+ Pair(typename TupleAccessTraits<T1>::ParameterType t1, T2& t2, T3& t3, T4& t4, T5& t5,
+ T6& t6, T7& t7, T8& t8, T9& t9);
+
+ /**
+ * @brief Constructor
+ *
+ * @param t1 The value of the first field.
+ * @param t2 The value of the second field.
+ */
+ Pair(typename TupleAccessTraits<Type1>::ParameterType t1, TT& t2);
+
+ Pair();
+
+ /**
+ * @brief Copy Constructor for implicit type conversion
+ * @param other The tuple to copy.
+ */
+ template<typename U1, typename U2>
+ Pair(const Pair<U1,U2>& other);
+
+ /**
+ * @brief Assignment operator for implicit type conversion
+ * @param other The tuple to assign.
+ */
+ template<typename U1, typename U2>
+ Pair& operator=(const Pair<U1,U2>& other);
+
+ Pair& operator=(const Pair& other);
+
+ /**
+ * @brief Get the first value
+ * @return The first value
+ */
+ typename TupleAccessTraits<Type1>::NonConstType first();
+
+ /**
+ * @brief Get the first value
+ * @return The first value
+ */
+ typename TupleAccessTraits<Type1>::ConstType
+ first() const;
+
+ /**
+ * @brief Get the second value
+ * @return The second value
+ */
+ typename TupleAccessTraits<Type2>::NonConstType
+ second();
+
+ /**
+ * @brief Get the second value
+ * @return The second value
+ */
+ typename TupleAccessTraits<Type2>::ConstType
+ second() const;
+
+ /** @brief The value of the first field. */
+ Type1 first_;
+ /** @brief The value of the second field. */
+ Type2 second_;
+
+ };
+
+ /**
+ * @brief A tuple consisting of one object.
+ * Specialization of Pair that really is a single value.
+ */
+ template<typename T1>
+ struct Pair<T1,Nil>
+ {
+ /**
+ * @brief The type of the first field.
+ */
+ typedef T1 Type1;
+
+ /**
+ * @brief The type of the (non-existent) second field is Nil.
+ * This typedef is useful in template metaprogramming, since it allows
+ * you to specialise for Nil instead of Pair<T, Nil>
+ */
+ typedef Nil Type2;
+
+ /**
+ * @brief Constructor.
+ * @param first The values for the first field.
+ */
+ Pair(typename TupleAccessTraits<T1>::ParameterType first, const Nil&, const Nil&, const Nil&, const Nil&,
+ const Nil&, const Nil&, const Nil&, const Nil&);
+
+ /**
+ * @brief Constructor.
+ * @param first The values for the first field.
+ */
+ Pair(typename TupleAccessTraits<T1>::ParameterType first,
+ const Nil&);
+
+ Pair();
+
+ /**
+ * @brief Copy constructor for type conversion.
+ */
+ template<typename T2>
+ Pair(const Pair<T2,Nil>& other);
+
+ /**
+ * @brief Assignment operator for type conversion.
+ */
+ template<typename T2>
+ Pair& operator=(const Pair<T2,Nil>& other);
+
+ /**
+ * @brief Assignment operator.
+ */
+ Pair& operator=(const Pair& other);
+
+ /**
+ * @brief Get the first value
+ * @return The first value
+ */
+ typename TupleAccessTraits<Type1>::NonConstType
+ first();
+
+ /**
+ * @brief Get the first value
+ * @return The first value
+ */
+ typename TupleAccessTraits<Type1>::ConstType
+ first() const;
+
+ /** @brief The value of the first field.*/
+ Type1 first_;
+ };
+
+
+ /**
+ * @brief Converts the Tuple to a list of pairs.
+ */
+ template<typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9>
+ struct TupleToPairs
+ {
+ typedef Pair<T1, typename TupleToPairs<T2,T3,T4,T5,T6,T7,T8,T9,Nil>::Type > Type;
+ };
+
+ /**
+ * @brief Specialization for a tuple consisting only of one type.
+ */
+ template<typename T1>
+ struct TupleToPairs<T1,Nil,Nil,Nil,Nil,Nil,Nil,Nil,Nil>
+ {
+ typedef Pair<T1,Nil> Type;
+ };
+
+ /**
+ * @brief A Tuple of objects.
+ *
+ * A maximum of 9 objects is supported.
+ *
+ * Use the following construction to access the individual elements.
+ \code
+ tuple<std::string, float*, int> my_tuple;
+
+ std:string& s = get<0>(my_tuple);
+ float* p = get<1>(my_tuple);
+
+ // Access the third element in a generic way
+ typedef tuple_element<2, tuple<std::string, float*, int> >::type Type;
+ Type& i = get<2>(my_tuple);
+ \endcode
+ */
+ template<typename T1 = Nil, typename T2 = Nil, typename T3 = Nil,
+ typename T4 = Nil, typename T5 = Nil,typename T6 = Nil,
+ typename T7 = Nil, typename T8 = Nil, typename T9 = Nil>
+ class tuple : public TupleToPairs<T1,T2,T3,T4,T5,T6,T7,T8,T9>::Type
+ {
+ public:
+ //! Type of the first Pair defining the Tuple
+ typedef typename TupleToPairs<T1,T2,T3,T4,T5,T6,T7,T8,T9>::Type FirstPair;
+
+ tuple()
+ {}
+
+ tuple(typename TupleAccessTraits<T1>::ParameterType t1)
+ : FirstPair(t1, nullType(), nullType(), nullType(),
+ nullType(), nullType(), nullType(), nullType(),
+ nullType())
+ {}
+
+ tuple(typename TupleAccessTraits<T1>::ParameterType t1,
+ typename TupleAccessTraits<T2>::ParameterType t2)
+ : FirstPair(t1, t2, nullType(), nullType(),
+ nullType(), nullType(), nullType(), nullType(),
+ nullType())
+ {}
+
+ tuple(typename TupleAccessTraits<T1>::ParameterType t1,
+ typename TupleAccessTraits<T2>::ParameterType t2,
+ typename TupleAccessTraits<T3>::ParameterType t3)
+ : FirstPair(t1, t2, t3, nullType(),
+ nullType(), nullType(), nullType(), nullType(),
+ nullType())
+ {}
+
+ tuple(typename TupleAccessTraits<T1>::ParameterType t1,
+ typename TupleAccessTraits<T2>::ParameterType t2,
+ typename TupleAccessTraits<T3>::ParameterType t3,
+ typename TupleAccessTraits<T4>::ParameterType t4)
+ : FirstPair(t1, t2, t3, t4,
+ nullType(), nullType(), nullType(), nullType(),
+ nullType())
+ {}
+
+ tuple(typename TupleAccessTraits<T1>::ParameterType t1,
+ typename TupleAccessTraits<T2>::ParameterType t2,
+ typename TupleAccessTraits<T3>::ParameterType t3,
+ typename TupleAccessTraits<T4>::ParameterType t4,
+ typename TupleAccessTraits<T5>::ParameterType t5)
+ : FirstPair(t1, t2, t3, t4,
+ t5, nullType(), nullType(), nullType(),
+ nullType())
+ {}
+
+ tuple(typename TupleAccessTraits<T1>::ParameterType t1,
+ typename TupleAccessTraits<T2>::ParameterType t2,
+ typename TupleAccessTraits<T3>::ParameterType t3,
+ typename TupleAccessTraits<T4>::ParameterType t4,
+ typename TupleAccessTraits<T5>::ParameterType t5,
+ typename TupleAccessTraits<T6>::ParameterType t6)
+ : FirstPair(t1, t2, t3, t4,
+ t5, t6, nullType(), nullType(),
+ nullType())
+ {}
+
+ tuple(typename TupleAccessTraits<T1>::ParameterType t1,
+ typename TupleAccessTraits<T2>::ParameterType t2,
+ typename TupleAccessTraits<T3>::ParameterType t3,
+ typename TupleAccessTraits<T4>::ParameterType t4,
+ typename TupleAccessTraits<T5>::ParameterType t5,
+ typename TupleAccessTraits<T6>::ParameterType t6,
+ typename TupleAccessTraits<T7>::ParameterType t7)
+ : FirstPair(t1, t2, t3, t4,
+ t5, t6, t7, nullType(),
+ nullType())
+ {}
+
+ tuple(typename TupleAccessTraits<T1>::ParameterType t1,
+ typename TupleAccessTraits<T2>::ParameterType t2,
+ typename TupleAccessTraits<T3>::ParameterType t3,
+ typename TupleAccessTraits<T4>::ParameterType t4,
+ typename TupleAccessTraits<T5>::ParameterType t5,
+ typename TupleAccessTraits<T6>::ParameterType t6,
+ typename TupleAccessTraits<T7>::ParameterType t7,
+ typename TupleAccessTraits<T8>::ParameterType t8)
+ : FirstPair(t1, t2, t3, t4,
+ t5, t6, t7, t8,
+ nullType())
+ {}
+
+ tuple(typename TupleAccessTraits<T1>::ParameterType t1,
+ typename TupleAccessTraits<T2>::ParameterType t2,
+ typename TupleAccessTraits<T3>::ParameterType t3,
+ typename TupleAccessTraits<T4>::ParameterType t4,
+ typename TupleAccessTraits<T5>::ParameterType t5,
+ typename TupleAccessTraits<T6>::ParameterType t6,
+ typename TupleAccessTraits<T7>::ParameterType t7,
+ typename TupleAccessTraits<T8>::ParameterType t8,
+ typename TupleAccessTraits<T9>::ParameterType t9)
+ : FirstPair(t1, t2, t3, t4, t5, t6, t7, t8, t9)
+ {}
+
+ template<class U1, class U2>
+ tuple& operator=(const Pair<U1,U2>& other)
+ {
+ FirstPair::operator=(other);
+ return *this;
+ }
+ };
+
+#endif
+
+#ifdef HAVE_TUPLE
+ using std::tuple_element;
+#elif defined HAVE_TR1_TUPLE
+ using std::tr1::tuple_element;
+#else
+ /**
+ * @brief Get the type of the N-th element of the tuple.
+ */
+ template<int N, class Tuple>
+ struct tuple_element
+ {
+ /**
+ * @brief The type of the N-th element of the tuple.
+ */
+ typedef typename tuple_element<N,typename Tuple::FirstPair>::type type;
+ typedef typename tuple_element<N,typename Tuple::FirstPair>::type Type;
+ };
+
+ template<int N, typename T1, typename T2>
+ struct tuple_element<N,Pair<T1,T2> >
+ {
+ /**
+ * @brief The type of the N-th element of the tuple.
+ */
+ typedef typename tuple_element<N-1,T2>::Type type;
+ typedef typename tuple_element<N-1,T2>::Type Type;
+ };
+
+ /**
+ * @brief Get the type of the first element of the tuple.
+ */
+ template<typename T1, typename T2>
+ struct tuple_element<0, Pair<T1,T2> >
+ {
+ /**
+ * @brief The type of the first element of the tuple.
+ */
+ typedef T1 type;
+ typedef T1 Type;
+ };
+
+#endif
+
+#if defined HAVE_TUPLE || defined HAVE_TR1_TUPLE
+#ifdef HAVE_TUPLE
+ using std::get;
+#elif defined HAVE_TR1_TUPLE
+ using std::tr1::get;
+#endif
+
+#else
+ /**
+ * @brief Get the N-th element of a tuple.
+ *
+ * \warning This is an internal class. Do no use it directly!
+ */
+ template<int N>
+ struct Element
+ {
+ /**
+ * @brief Get the N-th element of the tuple.
+ * @param tuple The tuple whose N-th element we want.
+ * @return The N-th element of the tuple.
+ */
+ template<typename T1, typename T2>
+ static typename TupleAccessTraits<
+ typename tuple_element<N,Pair<T1,T2> >::type
+ >::NonConstType
+ get(Pair<T1,T2>& tuple)
+ {
+ return Element<N-1>::get(tuple.second());
+ }
+
+ /**
+ * @brief Get the N-th element of the tuple.
+ * @param tuple The tuple whose N-th element we want.
+ * @return The N-th element of the tuple.
+ */
+ template<typename T1, typename T2>
+ static typename TupleAccessTraits<
+ typename tuple_element<N,Pair<T1,T2> >::type
+ >::ConstType
+ get(const Pair<T1,T2>& tuple)
+ {
+ return Element<N-1>::get(tuple.second());
+ }
+ };
+
+ /**
+ * @brief Get the first element of a tuple.
+ */
+ template<>
+ struct Element<0>
+ {
+ /**
+ * @brief Get the first element of the tuple.
+ * @param tuple The tuple whose first element we want.
+ * @return The first element of the tuple.
+ */
+ template<typename T1, typename T2>
+ static typename TupleAccessTraits<T1>::NonConstType get(Pair<T1,T2>& tuple)
+ {
+ return tuple.first();
+ }
+
+ /**
+ * @brief Get the first element of the tuple.
+ * @param tuple The tuple whose first element we want.
+ * @return The first element of the tuple.
+ */
+ template<typename T1, typename T2>
+ static typename TupleAccessTraits<T1>::ConstType get(const Pair<T1,T2>& tuple)
+ {
+ return tuple.first();
+ }
+ };
+
+ template<int i, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename T6, typename T7, typename T8, typename T9>
+ typename TupleAccessTraits<typename tuple_element<i, tuple<T1,T2,T3,T4,T5,T6,T7,T8,T9> >::type>
+ ::NonConstType
+ get(tuple<T1,T2,T3,T4,T5,T6,T7,T8,T9>& t)
+ {
+ return Element<i>::get(t);
+ }
+
+ template<int i, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename T6, typename T7, typename T8, typename T9>
+ typename TupleAccessTraits<typename tuple_element<i, tuple<T1,T2,T3,T4,T5,T6,T7,T8,T9> >::type>
+ ::ConstType
+ get(const tuple<T1,T2,T3,T4,T5,T6,T7,T8,T9>& t)
+ {
+ return Element<i>::get(t);
+ }
+
+#endif
+
+#ifdef HAVE_TUPLE
+ using std::tuple_size;
+#elif defined HAVE_TR1_TUPLE
+ using std::tr1::tuple_size;
+#else
+ /**
+ * @brief Template meta_programm to query the size of a tuple
+ *
+ */
+ template<class T>
+ struct tuple_size
+ {
+ enum {
+ // @brief The number of Elements in the tuple.
+ value=tuple_size<typename T::FirstPair>::value
+ };
+
+
+ };
+
+ template<typename T1, typename T2>
+ struct tuple_size<Pair<T1,T2> >
+ {
+ enum { value=1+tuple_size<T2>::value};
+ };
+
+
+ template<typename T1>
+ struct tuple_size<Pair<T1,Nil> >
+ {
+ enum { value=1};
+ };
+
+ template<>
+ struct tuple_size<Pair<Nil,Nil> >
+ {
+ enum { value=0};
+ };
+#endif
+
+
+#ifdef HAVE_TUPLE
+ using std::tie;
+ using std::make_tuple;
+#elif defined HAVE_TR1_TUPLE
+ using std::tr1::tie;
+ using std::tr1::make_tuple;
+#endif
+
+
+ template<int i>
+ struct tuple_writer
+ {
+ template<class T>
+ static std::ostream& put(std::ostream& os, const T& t, const char* delim=", ")
+ {
+ return tuple_writer<i-1>::put(os,t,delim)<<delim<<Dune::get<i-1>(t);
+ }
+
+ template< class T >
+ static std::istream &get ( std::istream &is, T &t, const char *delim = "," )
+ {
+ tuple_writer< i-1 >::get( is, t, delim );
+ for( const char *it = delim; is && (*it != 0); ++it )
+ {
+ char c = 0;
+ is >> c;
+ if( c != *it )
+ is.setstate( std::ios::failbit );
+ }
+ return is >> Dune::get< i-1 >( t );
+ }
+ };
+
+ template<>
+ struct tuple_writer<1>
+ {
+ template<class T>
+ static std::ostream& put(std::ostream& os, const T& t, const char* delim=", ")
+ {
+ DUNE_UNUSED_PARAMETER(delim);
+ return os<<Dune::get<0>(t);
+ }
+
+ template< class T >
+ static std::istream &get ( std::istream &is, T &t, const char *delim = ", " )
+ {
+ return is >> Dune::get< 0 >( t );
+ }
+ };
+
+ template<>
+ struct tuple_writer<0>
+ {
+ template<class T>
+ static std::ostream& put(std::ostream& os, const T& t, const char* delim=", ")
+ {
+ return os;
+ }
+
+ template< class T >
+ static std::istream &get ( std::istream &is, T &t, const char *delim = ", " )
+ {
+ return is;
+ }
+ };
+
+#if defined HAVE_TUPLE || defined HAVE_TR1_TUPLE
+ /**
+ * \brief Print a tuple.
+ */
+ template<typename T1>
+ inline std::ostream& operator<<( std::ostream& os, const tuple<T1> & t)
+ {
+ typedef tuple<T1> TupleT;
+ return tuple_writer<tuple_size<TupleT>::value>::put(os, t);
+ }
+
+ template<typename T1, typename T2>
+ inline std::ostream& operator<<( std::ostream& os, const tuple<T1,T2> & t)
+ {
+ typedef tuple<T1,T2> TupleT;
+ return tuple_writer<tuple_size<TupleT>::value>::put(os, t);
+ }
+
+ template<typename T1, typename T2, typename T3>
+ inline std::ostream& operator<<( std::ostream& os, const tuple<T1,T2,T3> & t)
+ {
+ typedef tuple<T1,T2,T3> TupleT;
+ return tuple_writer<tuple_size<TupleT>::value>::put(os, t);
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4>
+ inline std::ostream& operator<<( std::ostream& os, const tuple<T1,T2,T3,T4> & t)
+ {
+ typedef tuple<T1,T2,T3,T4> TupleT;
+ return tuple_writer<tuple_size<TupleT>::value>::put(os, t);
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5>
+ inline std::ostream& operator<<( std::ostream& os, const tuple<T1,T2,T3,T4,T5> & t)
+ {
+ typedef tuple<T1,T2,T3,T4,T5> TupleT;
+ return tuple_writer<tuple_size<TupleT>::value>::put(os, t);
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+ inline std::ostream& operator<<( std::ostream& os, const tuple<T1,T2,T3,T4,T5,T6> & t)
+ {
+ typedef tuple<T1,T2,T3,T4,T5,T6> TupleT;
+ return tuple_writer<tuple_size<TupleT>::value>::put(os, t);
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
+ inline std::ostream& operator<<( std::ostream& os, const tuple<T1,T2,T3,T4,T5,T6,T7> & t)
+ {
+ typedef tuple<T1,T2,T3,T4,T5,T6,T7> TupleT;
+ return tuple_writer<tuple_size<TupleT>::value>::put(os, t);
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7,
+ typename T8>
+ inline std::ostream& operator<<( std::ostream& os, const tuple<T1,T2,T3,T4,T5,T6,T7,T8> & t)
+ {
+ typedef tuple<T1,T2,T3,T4,T5,T6,T7,T8> TupleT;
+ return tuple_writer<tuple_size<TupleT>::value>::put(os, t);
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7,
+ typename T8, typename T9>
+ inline std::ostream& operator<<( std::ostream& os, const tuple<T1,T2,T3,T4,T5,T6,T7,T8,T9> & t)
+ {
+ typedef tuple<T1,T2,T3,T4,T5,T6,T7,T8,T9> TupleT;
+ return tuple_writer<tuple_size<TupleT>::value>::put(os, t);
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7,
+ typename T8, typename T9, typename T10>
+ inline std::ostream& operator<<( std::ostream& os, const tuple<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10> & t)
+ {
+ typedef tuple<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10> TupleT;
+ return tuple_writer<tuple_size<TupleT>::value>::put(os, t);
+ }
+
+ /**
+ * \brief Read a tuple.
+ */
+ template<typename T1>
+ inline std::istream& operator>>( std::istream& is, tuple<T1> & t)
+ {
+ typedef tuple<T1> TupleT;
+ return tuple_writer<tuple_size<TupleT>::value>::get(is, t);
+ }
+
+ template<typename T1, typename T2>
+ inline std::istream& operator>>( std::istream& is, tuple<T1,T2> & t)
+ {
+ typedef tuple<T1,T2> TupleT;
+ return tuple_writer<tuple_size<TupleT>::value>::get(is, t);
+ }
+
+ template<typename T1, typename T2, typename T3>
+ inline std::istream& operator>>( std::istream& is, tuple<T1,T2,T3> & t)
+ {
+ typedef tuple<T1,T2,T3> TupleT;
+ return tuple_writer<tuple_size<TupleT>::value>::get(is, t);
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4>
+ inline std::istream& operator>>( std::istream& is, tuple<T1,T2,T3,T4> & t)
+ {
+ typedef tuple<T1,T2,T3,T4> TupleT;
+ return tuple_writer<tuple_size<TupleT>::value>::get(is, t);
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5>
+ inline std::istream& operator>>( std::istream& is, tuple<T1,T2,T3,T4,T5> & t)
+ {
+ typedef tuple<T1,T2,T3,T4,T5> TupleT;
+ return tuple_writer<tuple_size<TupleT>::value>::get(is, t);
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+ inline std::istream& operator>>( std::istream& is, tuple<T1,T2,T3,T4,T5,T6> & t)
+ {
+ typedef tuple<T1,T2,T3,T4,T5,T6> TupleT;
+ return tuple_writer<tuple_size<TupleT>::value>::get(is, t);
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
+ inline std::istream& operator>>( std::istream& is, tuple<T1,T2,T3,T4,T5,T6,T7> & t)
+ {
+ typedef tuple<T1,T2,T3,T4,T5,T6,T7> TupleT;
+ return tuple_writer<tuple_size<TupleT>::value>::get(is, t);
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7,
+ typename T8>
+ inline std::istream& operator>>( std::istream& is, tuple<T1,T2,T3,T4,T5,T6,T7,T8> & t)
+ {
+ typedef tuple<T1,T2,T3,T4,T5,T6,T7,T8> TupleT;
+ return tuple_writer<tuple_size<TupleT>::value>::get(is, t);
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7,
+ typename T8, typename T9>
+ inline std::istream& operator>>( std::istream& is, tuple<T1,T2,T3,T4,T5,T6,T7,T8,T9> & t)
+ {
+ typedef tuple<T1,T2,T3,T4,T5,T6,T7,T8,T9> TupleT;
+ return tuple_writer<tuple_size<TupleT>::value>::get(is, t);
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7,
+ typename T8, typename T9, typename T10>
+ inline std::istream& operator>>( std::istream& is, tuple<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10> & t)
+ {
+ typedef tuple<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10> TupleT;
+ return tuple_writer<tuple_size<TupleT>::value>::get(is, t);
+ }
+#else
+ /**
+ * @brief Equality comparison operator for tuples.
+ * @param tuple1 The first tuple.
+ * @param tuple2 The second tuple,
+ */
+ template<typename T1, typename T2, typename U1, typename U2>
+ inline bool operator==(const Pair<T1,T2>& tuple1, const Pair<U1,U2>& tuple2)
+ {
+ return (tuple1.first()==tuple2.first() && tuple1.second()==tuple2.second());
+ }
+
+ /**
+ * @brief Inequality comparison operator for tuples.
+ * @param tuple1 The first tuple.
+ * @param tuple2 The second tuple,
+ */
+ template<typename T1, typename T2, typename U1, typename U2>
+ inline bool operator!=(const Pair<T1,T2>& tuple1, const Pair<U1,U2>& tuple2)
+ {
+ return (tuple1.first()!=tuple2.first() || tuple1.second()!=tuple2.second());
+ }
+
+ /**
+ * @brief Less operator for tuples.
+ * @param tuple1 The first tuple.
+ * @param tuple2 The second tuple,
+ */
+ template<typename T1, typename T2, typename U1, typename U2>
+ inline bool operator<(const Pair<T1,T2>& tuple1, const Pair<U1,U2>& tuple2)
+ {
+ return tuple1.first() < tuple2.first()
+ || (tuple1.first() == tuple2.first() && tuple1.second() < tuple2.second());
+ }
+
+ /**
+ * @brief Equality comparison operator for tuples.
+ * @param tuple1 The first tuple.
+ * @param tuple2 The second tuple,
+ */
+ template<typename T1,typename U1>
+ inline bool operator==(const Pair<T1,Nil>& tuple1, const Pair<U1,Nil>& tuple2)
+ {
+ return (tuple1.first()==tuple2.first());
+ }
+
+ /**
+ * @brief Inequality comparison operator for tuples.
+ * @param tuple1 The first tuple.
+ * @param tuple2 The second tuple,
+ */
+ template<typename T1, typename U1>
+ inline bool operator!=(const Pair<T1,Nil>& tuple1, const Pair<U1,Nil>& tuple2)
+ {
+ dune_static_assert( (IsInteroperable<T1,U1>::value),
+ "T1 and U1 have to be interoperable, i.e., either "
+ "conversion from one to the other must exist." );
+ return (tuple1.first()!=tuple2.first());
+ }
+
+ /**
+ * @brief Less operator for tuples.
+ * @param tuple1 The first tuple.
+ * @param tuple2 The second tuple,
+ */
+ template<typename T1, typename U1>
+ inline bool operator<(const Pair<T1,Nil>& tuple1, const Pair<U1,Nil>& tuple2)
+ {
+ return (tuple1.first()<tuple2.first());
+ }
+
+ /**
+ * @brief Equality comparison operator for tuples.
+ *
+ * @param tuple1 The first tuple.
+ * @param tuple2 The second tuple.
+ * @return False as the type of the compared objects are different.
+ */
+ template<typename T1,typename U1, typename U2>
+ inline bool operator==(const Pair<T1,Nil>& tuple1, const Pair<U1,U2>& tuple2)
+ {
+ return false;
+ }
+
+ /**
+ * @brief Inequality comparison operator for tuples.
+ * @param tuple1 The first tuple.
+ * @param tuple2 The second tuple.
+ * @return True as the type of the compared objects are different.
+ */
+ template<typename T1, typename U1, typename U2>
+ inline bool operator!=(const Pair<T1,Nil>& tuple1, const Pair<U1,U2>& tuple2)
+ {
+ return true;
+ }
+
+
+ /**
+ * @brief Equality comparison operator for tuples.
+ * @param tuple1 The first tuple.
+ * @param tuple2 The second tuple.
+ * @return False as the type of the compared objects are different.
+ */
+ template<typename T1, typename T2, typename U1>
+ inline bool operator==(const Pair<T1,T2>& tuple1, const Pair<U1,Nil>& tuple2)
+ {
+ return false;
+ }
+
+ /**
+ * @brief Inequality comparison operator for tuples.
+ * @param tuple1 The first tuple.
+ * @param tuple2 The second tuple.
+ * @return True as the type of the compared objects are different.
+ */
+ template<typename T1, typename T2, typename U1>
+ inline bool operator!=(const Pair<T1,T2>& tuple1, const Pair<U1,Nil>& tuple2)
+ {
+ return true;
+ }
+
+ /**
+ * @brief Create a tuple and initialize it.
+ * @param first The value of the first field.
+ * @param second The value of the second field.
+ */
+ template<typename T1, typename T2>
+ inline Pair<T1,T2> makePair(const T1& first, const T2& second)
+ {
+ return Pair<T1,T2>(first, second);
+ }
+
+ /**
+ * @brief Print a pair or tuple.
+ */
+ template<typename T1, typename T2>
+ inline std::ostream& operator<<(std::ostream& os, const Pair<T1,T2>& pair)
+ {
+ os<<pair.first()<<" "<<pair.second();
+ return os;
+ }
+
+ template<typename T1>
+ inline std::ostream& operator<<(std::ostream& os, const Pair<T1,Nil>& pair)
+ {
+ os<<pair.first();
+ return os;
+ }
+
+ /**
+ * @brief Read a pair or tuple.
+ */
+ template<typename T1, typename T2>
+ inline std::istream& operator>>(std::istream& is, Pair<T1,T2>& pair)
+ {
+ return is >> pair.first() >> pair.second();
+ }
+
+ template<typename T1>
+ inline std::istream& operator>>(std::istream& is, Pair<T1,Nil>& pair)
+ {
+ return is >> pair.first();
+ }
+
+ template<class T1>
+ inline tuple<T1&> tie(T1& t1) {
+ return tuple<T1&> (t1);
+ }
+
+ template<class T1, class T2>
+ inline tuple<T1&, T2&> tie(T1& t1, T2& t2) {
+ return tuple<T1&, T2&> (t1, t2);
+ }
+
+ template<class T1, class T2, class T3>
+ inline tuple<T1&, T2&, T3&> tie(T1& t1, T2& t2, T3& t3) {
+ return tuple<T1&, T2&, T3&> (t1, t2, t3);
+ }
+
+ template<class T1, class T2, class T3, class T4>
+ inline tuple<T1&, T2&, T3&, T4&> tie(T1& t1, T2& t2, T3& t3, T4& t4) {
+ return tuple<T1&, T2&, T3&, T4&> (t1, t2, t3, t4);
+ }
+
+ template<class T1, class T2, class T3, class T4, class T5>
+ inline tuple<T1&, T2&, T3&, T4&, T5&>
+ tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) {
+ return tuple<T1&, T2&, T3&, T4&, T5&> (t1, t2, t3, t4, t5);
+ }
+
+ template<class T1, class T2, class T3, class T4, class T5, class T6>
+ inline tuple<T1&, T2&, T3&, T4&, T5&, T6&>
+ tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6) {
+ return tuple<T1&, T2&, T3&, T4&, T5&, T6&> (t1, t2, t3, t4, t5, t6);
+ }
+
+ template<class T1, class T2, class T3, class T4, class T5, class T6, class T7>
+ inline tuple<T1&, T2&, T3&, T4&, T5&, T6&, T7&>
+ tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7) {
+ return tuple<T1&, T2&, T3&, T4&, T5&, T6&, T7&> (t1, t2, t3, t4, t5, t6, t7);
+ }
+
+ template<class T1, class T2, class T3, class T4, class T5, class T6, class T7,
+ class T8>
+ inline tuple<T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&>
+ tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8) {
+ return tuple<T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&>
+ (t1, t2, t3, t4, t5, t6, t7, t8);
+ }
+
+ template<class T1, class T2, class T3, class T4, class T5, class T6, class T7,
+ class T8, class T9>
+ inline tuple<T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&, T9&>
+ tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8, T9& t9) {
+ return tuple<T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&, T9&>
+ (t1, t2, t3, t4, t5, t6, t7, t8, t9);
+ }
+
+ template<class T1>
+ inline tuple<T1> make_tuple(const T1& t1) {
+ return tuple<T1> (t1);
+ }
+
+ template<class T1, class T2>
+ inline tuple<T1, T2> make_tuple(const T1& t1, const T2& t2) {
+ return tuple<T1, T2> (t1, t2);
+ }
+
+ template<class T1, class T2, class T3>
+ inline tuple<T1, T2, T3> make_tuple(const T1& t1, const T2& t2, const T3& t3) {
+ return tuple<T1, T2, T3> (t1, t2, t3);
+ }
+
+ template<class T1, class T2, class T3, class T4>
+ inline tuple<T1, T2, T3, T4> make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4) {
+ return tuple<T1, T2, T3, T4> (t1, t2, t3, t4);
+ }
+
+ template<class T1, class T2, class T3, class T4, class T5>
+ inline tuple<T1, T2, T3, T4, T5>
+ make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5) {
+ return tuple<T1, T2, T3, T4, T5> (t1, t2, t3, t4, t5);
+ }
+
+ template<class T1, class T2, class T3, class T4, class T5, class T6>
+ inline tuple<T1, T2, T3, T4, T5, T6>
+ make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6) {
+ return tuple<T1, T2, T3, T4, T5, T6> (t1, t2, t3, t4, t5, t6);
+ }
+
+ template<class T1, class T2, class T3, class T4, class T5, class T6, class T7>
+ inline tuple<T1, T2, T3, T4, T5, T6, T7>
+ make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6,
+ const T7& t7) {
+ return tuple<T1, T2, T3, T4, T5, T6, T7> (t1, t2, t3, t4, t5, t6, t7);
+ }
+
+ template<class T1, class T2, class T3, class T4, class T5, class T6, class T7,
+ class T8>
+ inline tuple<T1, T2, T3, T4, T5, T6, T7, T8>
+ make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6,
+ const T7& t7, const T8& t8) {
+ return tuple<T1, T2, T3, T4, T5, T6, T7, T8>
+ (t1, t2, t3, t4, t5, t6, t7, t8);
+ }
+
+ template<class T1, class T2, class T3, class T4, class T5, class T6, class T7,
+ class T8, class T9>
+ inline tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>
+ make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6,
+ const T7& t7, const T8& t8, const T9& t9) {
+ return tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>
+ (t1, t2, t3, t4, t5, t6, t7, t8, t9);
+ }
+
+ template<typename T1, typename TT>
+ template<typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9>
+ inline Pair<T1,TT>::Pair(typename TupleAccessTraits<T1>::ParameterType first,
+ T2& t2, T3& t3, T4& t4, T5& t5,
+ T6& t6, T7& t7, T8& t8, T9& t9)
+ : first_(first), second_(t2,t3,t4,t5,t6,t7,t8,t9, nullType())
+ {}
+
+ template <typename T1, typename TT>
+ inline Pair<T1, TT>::Pair(typename TupleAccessTraits<T1>::ParameterType first, TT& second)
+ : first_(first), second_(second)
+ {}
+
+ template<typename T1, typename T2>
+ inline Pair<T1,T2>::Pair()
+ : first_(), second_()
+ {}
+
+ template<typename T1, typename T2>
+ template<typename U1, typename U2>
+ inline Pair<T1,T2>::Pair(const Pair<U1,U2>& other)
+ : first_(other.first_), second_(other.second_)
+ {}
+
+ template<typename T1, typename T2>
+ template<typename U1, typename U2>
+ inline Pair<T1,T2>& Pair<T1,T2>::operator=(const Pair<U1,U2>& other)
+ {
+ first_=other.first_;
+ second_=other.second_;
+ return *this;
+ }
+
+ template<typename T1, typename T2>
+ inline Pair<T1,T2>& Pair<T1,T2>::operator=(const Pair& other)
+ {
+ first_=other.first_;
+ second_=other.second_;
+ return *this;
+ }
+
+ template<typename T1, typename T2>
+ inline typename TupleAccessTraits<T1>::NonConstType
+ Pair<T1,T2>::first()
+ {
+ return first_;
+ }
+
+ template<typename T1, typename T2>
+ inline typename TupleAccessTraits<T1>::ConstType
+ Pair<T1,T2>::first() const
+ {
+ return first_;
+ }
+
+
+ template<typename T1, typename T2>
+ inline typename TupleAccessTraits<T2>::NonConstType
+ Pair<T1,T2>::second()
+ {
+ return second_;
+ }
+
+ template<typename T1, typename T2>
+ inline typename TupleAccessTraits<T2>::ConstType
+ Pair<T1,T2>::second() const
+ {
+ return second_;
+ }
+
+ template<typename T1>
+ inline Pair<T1,Nil>::Pair(typename TupleAccessTraits<T1>::ParameterType first,
+ const Nil&, const Nil&, const Nil&, const Nil&,
+ const Nil&, const Nil&, const Nil&, const Nil&)
+ : first_(first)
+ {}
+
+ template <typename T1>
+ inline Pair<T1, Nil>::Pair(typename TupleAccessTraits<T1>::ParameterType first,
+ const Nil&)
+ : first_(first)
+ {}
+
+ template<typename T1>
+ inline Pair<T1,Nil>::Pair()
+ : first_()
+ {}
+
+ template<typename T1>
+ template<typename T2>
+ inline Pair<T1,Nil>::Pair(const Pair<T2,Nil>& other)
+ : first_(other.first_)
+ {}
+
+ template<typename T1>
+ template<typename T2>
+ Pair<T1,Nil>& Pair<T1,Nil>::operator=(const Pair<T2,Nil>& other)
+ {
+ first_ = other.first_;
+ return *this;
+ }
+
+
+ template<typename T1>
+ Pair<T1,Nil>& Pair<T1,Nil>::operator=(const Pair& other)
+ {
+ first_ = other.first_;
+ return *this;
+ }
+
+ template<typename T1>
+ inline typename TupleAccessTraits<T1>::NonConstType
+ Pair<T1,Nil>::first()
+ {
+ return first_;
+ }
+
+ template<typename T1>
+ inline typename TupleAccessTraits<T1>::ConstType
+ Pair<T1,Nil>::first() const
+ {
+ return first_;
+ }
+
+ /** }@ */
+#endif
+}
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+
+#ifndef DUNE_TUPLE_UTILITY_HH
+#define DUNE_TUPLE_UTILITY_HH
+
+#include <cstddef>
+
+#include <dune/common/static_assert.hh>
+#include <dune/common/typetraits.hh>
+
+#include "tuples.hh"
+
+namespace Dune {
+
+ /** @ addtogroup Common
+ *
+ * @{
+ */
+
+ /**
+ * @file
+ * @brief Contains utility classes which can be used with tuples.
+ */
+
+ /**
+ * @brief A helper template that initializes a tuple consisting of pointers
+ * to NULL.
+ *
+ * A tuple of NULL pointers may be useful when you use a tuple of pointers
+ * in a class which you can only initialise in a later stage.
+ */
+ template <class Tuple>
+ class NullPointerInitialiser {
+ dune_static_assert(AlwaysFalse<Tuple>::value, "Attempt to use the "
+ "unspecialized version of NullPointerInitialiser. "
+ "NullPointerInitialiser needs to be specialized for "
+ "each possible tuple size. Naturally the number of "
+ "pre-defined specializations is limited arbitrarily. "
+ "Maybe you need to raise this limit by defining some "
+ "more specializations? Also check that the tuple this "
+ "is applied to really is a tuple of pointers only.");
+ public:
+ //! export the type of the tuples
+ typedef Tuple ResultType;
+ //! generate a zero-initialized tuple
+ static ResultType apply();
+ };
+
+#ifndef DOXYGEN
+ template<class Tuple>
+ struct NullPointerInitialiser<const Tuple>
+ : public NullPointerInitialiser<Tuple>
+ {
+ typedef const Tuple ResultType;
+ };
+
+ template<>
+ struct NullPointerInitialiser<tuple<> > {
+ typedef tuple<> ResultType;
+ static ResultType apply() {
+ return ResultType();
+ }
+ };
+
+ template<class T0>
+ struct NullPointerInitialiser<tuple<T0*> > {
+ typedef tuple<T0*> ResultType;
+ static ResultType apply() {
+ return ResultType(static_cast<T0*>(0));
+ }
+ };
+
+ template<class T0, class T1>
+ struct NullPointerInitialiser<tuple<T0*, T1*> > {
+ typedef tuple<T0*, T1*> ResultType;
+ static ResultType apply() {
+ return ResultType(static_cast<T0*>(0), static_cast<T1*>(0));
+ }
+ };
+
+ template<class T0, class T1, class T2>
+ struct NullPointerInitialiser<tuple<T0*, T1*, T2*> > {
+ typedef tuple<T0*, T1*, T2*> ResultType;
+ static ResultType apply() {
+ return ResultType(static_cast<T0*>(0), static_cast<T1*>(0),
+ static_cast<T2*>(0));
+ }
+ };
+
+ template<class T0, class T1, class T2, class T3>
+ struct NullPointerInitialiser<tuple<T0*, T1*, T2*, T3*> > {
+ typedef tuple<T0*, T1*, T2*, T3*> ResultType;
+ static ResultType apply() {
+ return ResultType(static_cast<T0*>(0), static_cast<T1*>(0),
+ static_cast<T2*>(0), static_cast<T3*>(0));
+ }
+ };
+
+ template<class T0, class T1, class T2, class T3, class T4>
+ struct NullPointerInitialiser<tuple<T0*, T1*, T2*, T3*, T4*> > {
+ typedef tuple<T0*, T1*, T2*, T3*, T4*> ResultType;
+ static ResultType apply() {
+ return ResultType(static_cast<T0*>(0), static_cast<T1*>(0),
+ static_cast<T2*>(0), static_cast<T3*>(0),
+ static_cast<T4*>(0));
+ }
+ };
+
+ template<class T0, class T1, class T2, class T3, class T4, class T5>
+ struct NullPointerInitialiser<tuple<T0*, T1*, T2*, T3*, T4*, T5*> > {
+ typedef tuple<T0*, T1*, T2*, T3*, T4*, T5*> ResultType;
+ static ResultType apply() {
+ return ResultType(static_cast<T0*>(0), static_cast<T1*>(0),
+ static_cast<T2*>(0), static_cast<T3*>(0),
+ static_cast<T4*>(0), static_cast<T5*>(0));
+ }
+ };
+
+ template<class T0, class T1, class T2, class T3, class T4, class T5,
+ class T6>
+ struct NullPointerInitialiser<tuple<T0*, T1*, T2*, T3*, T4*, T5*, T6*> > {
+ typedef tuple<T0*, T1*, T2*, T3*, T4*, T5*, T6*> ResultType;
+ static ResultType apply() {
+ return ResultType(static_cast<T0*>(0), static_cast<T1*>(0),
+ static_cast<T2*>(0), static_cast<T3*>(0),
+ static_cast<T4*>(0), static_cast<T5*>(0),
+ static_cast<T6*>(0));
+ }
+ };
+
+ template<class T0, class T1, class T2, class T3, class T4, class T5,
+ class T6, class T7>
+ struct NullPointerInitialiser<tuple<T0*, T1*, T2*, T3*, T4*, T5*, T6*,
+ T7*> > {
+ typedef tuple<T0*, T1*, T2*, T3*, T4*, T5*, T6*, T7*> ResultType;
+ static ResultType apply() {
+ return ResultType(static_cast<T0*>(0), static_cast<T1*>(0),
+ static_cast<T2*>(0), static_cast<T3*>(0),
+ static_cast<T4*>(0), static_cast<T5*>(0),
+ static_cast<T6*>(0), static_cast<T7*>(0));
+ }
+ };
+
+ template<class T0, class T1, class T2, class T3, class T4, class T5,
+ class T6, class T7, class T8>
+ struct NullPointerInitialiser<tuple<T0*, T1*, T2*, T3*, T4*, T5*, T6*,
+ T7*, T8*> > {
+ typedef tuple<T0*, T1*, T2*, T3*, T4*, T5*, T6*, T7*, T8*> ResultType;
+ static ResultType apply() {
+ return ResultType(static_cast<T0*>(0), static_cast<T1*>(0),
+ static_cast<T2*>(0), static_cast<T3*>(0),
+ static_cast<T4*>(0), static_cast<T5*>(0),
+ static_cast<T6*>(0), static_cast<T7*>(0),
+ static_cast<T8*>(0));
+ }
+ };
+
+ // template<class T0, class T1, class T2, class T3, class T4, class T5,
+ // class T6, class T7, class T8, class T9>
+ // struct NullPointerInitialiser<tuple<T0*, T1*, T2*, T3*, T4*, T5*, T6*,
+ // T7*, T8*, T9*> > {
+ // typedef tuple<T0*, T1*, T2*, T3*, T4*, T5*, T6*, T7*, T8*, T9*> ResultType;
+ // static ResultType apply() {
+ // return ResultType(static_cast<T0*>(0), static_cast<T1*>(0),
+ // static_cast<T2*>(0), static_cast<T3*>(0),
+ // static_cast<T4*>(0), static_cast<T5*>(0),
+ // static_cast<T6*>(0), static_cast<T7*>(0),
+ // static_cast<T8*>(0), static_cast<T9*>(0));
+ // }
+ // };
+#endif // !defined(DOXYGEN)
+
+ /**
+ * @brief Helper template to clone the type definition of a tuple with the
+ * storage types replaced by a user-defined rule.
+ *
+ * Suppose all storage types A_i in a tuple define a type A_i::B. You can
+ * build up a pair consisting of the types defined by A_i::B in the following
+ * way:
+ * \code
+ * template <class A>
+ * struct MyEvaluator {
+ * typedef typename A::B Type;
+ * };
+ *
+ * typedef ForEachType<MyEvaluator, ATuple>::Type BTuple;
+ * \endcode
+ * Here, MyEvaluator is a helper struct that extracts the correct type from
+ * the storage types of the tuple defined by the tuple ATuple.
+ *
+ * \sa AddRefTypeEvaluator, AddPtrTypeEvaluator, genericTransformTuple(),
+ * and transformTuple().
+ */
+ template <template <class> class TypeEvaluator, class TupleType>
+ class ForEachType {
+ dune_static_assert(AlwaysFalse<TupleType>::value, "Attempt to use the "
+ "unspecialized version of ForEachType. ForEachType "
+ "needs to be specialized for each possible tuple "
+ "size. Naturally the number of pre-defined "
+ "specializations is limited arbitrarily. Maybe you "
+ "need to raise this limit by defining some more "
+ "specializations?");
+ struct ImplementationDefined {};
+ public:
+ //! type of the transformed tuple
+ typedef ImplementationDefined Type;
+ };
+
+#ifndef DOXYGEN
+ template <template <class> class TE, class Tuple>
+ struct ForEachType<TE, const Tuple> {
+ typedef const typename ForEachType<TE, Tuple>::Type Type;
+ };
+
+ template <template <class> class TE>
+ struct ForEachType<TE, tuple<> > {
+ typedef tuple<> Type;
+ };
+
+ template <template <class> class TE, class T0>
+ struct ForEachType<TE, tuple<T0> > {
+ typedef tuple<typename TE<T0>::Type> Type;
+ };
+
+ template <template <class> class TE, class T0, class T1>
+ struct ForEachType<TE, tuple<T0, T1> > {
+ typedef tuple<typename TE<T0>::Type, typename TE<T1>::Type> Type;
+ };
+
+ template <template <class> class TE, class T0, class T1, class T2>
+ struct ForEachType<TE, tuple<T0, T1, T2> > {
+ typedef tuple<typename TE<T0>::Type, typename TE<T1>::Type,
+ typename TE<T2>::Type> Type;
+ };
+
+ template <template <class> class TE, class T0, class T1, class T2, class T3>
+ struct ForEachType<TE, tuple<T0, T1, T2, T3> > {
+ typedef tuple<typename TE<T0>::Type, typename TE<T1>::Type,
+ typename TE<T2>::Type, typename TE<T3>::Type> Type;
+ };
+
+ template <template <class> class TE, class T0, class T1, class T2, class T3,
+ class T4>
+ struct ForEachType<TE, tuple<T0, T1, T2, T3, T4> > {
+ typedef tuple<typename TE<T0>::Type, typename TE<T1>::Type,
+ typename TE<T2>::Type, typename TE<T3>::Type,
+ typename TE<T4>::Type> Type;
+ };
+
+ template <template <class> class TE, class T0, class T1, class T2, class T3,
+ class T4, class T5>
+ struct ForEachType<TE, tuple<T0, T1, T2, T3, T4, T5> > {
+ typedef tuple<typename TE<T0>::Type, typename TE<T1>::Type,
+ typename TE<T2>::Type, typename TE<T3>::Type,
+ typename TE<T4>::Type, typename TE<T5>::Type> Type;
+ };
+
+ template <template <class> class TE, class T0, class T1, class T2, class T3,
+ class T4, class T5, class T6>
+ struct ForEachType<TE, tuple<T0, T1, T2, T3, T4, T5, T6> > {
+ typedef tuple<typename TE<T0>::Type, typename TE<T1>::Type,
+ typename TE<T2>::Type, typename TE<T3>::Type,
+ typename TE<T4>::Type, typename TE<T5>::Type,
+ typename TE<T6>::Type> Type;
+ };
+
+ template <template <class> class TE, class T0, class T1, class T2, class T3,
+ class T4, class T5, class T6, class T7>
+ struct ForEachType<TE, tuple<T0, T1, T2, T3, T4, T5, T6, T7> > {
+ typedef tuple<typename TE<T0>::Type, typename TE<T1>::Type,
+ typename TE<T2>::Type, typename TE<T3>::Type,
+ typename TE<T4>::Type, typename TE<T5>::Type,
+ typename TE<T6>::Type, typename TE<T7>::Type> Type;
+ };
+
+ template <template <class> class TE, class T0, class T1, class T2, class T3,
+ class T4, class T5, class T6, class T7, class T8>
+ struct ForEachType<TE, tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8> > {
+ typedef tuple<typename TE<T0>::Type, typename TE<T1>::Type,
+ typename TE<T2>::Type, typename TE<T3>::Type,
+ typename TE<T4>::Type, typename TE<T5>::Type,
+ typename TE<T6>::Type, typename TE<T7>::Type,
+ typename TE<T8>::Type> Type;
+ };
+
+ // template <template <class> class TE, class T0, class T1, class T2, class T3,
+ // class T4, class T5, class T6, class T7, class T8, class T9>
+ // struct ForEachType<TE, tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> > {
+ // typedef tuple<typename TE<T0>::Type, typename TE<T1>::Type,
+ // typename TE<T2>::Type, typename TE<T3>::Type,
+ // typename TE<T4>::Type, typename TE<T5>::Type,
+ // typename TE<T6>::Type, typename TE<T7>::Type,
+ // typename TE<T8>::Type, typename TE<T9>::Type> Type;
+ // };
+#endif // !defined(DOXYGEN)
+
+ //////////////////////////////////////////////////////////////////////
+ //
+ // genericTransformTuple stuff
+ //
+
+ // genericTransformTuple() needs to be overloaded for each tuple size (we
+ // limit ourselves to tuple_size <= 10 here). For a given tuple size it
+ // needs to be overloaded for all combinations of const and non-const
+ // argument references. (On the one hand, we want to allow modifyable
+ // arguments, so const references alone are not sufficient. On the other
+ // hand, we also want to allow rvalues (literals) as argument, which do not
+ // bind to non-const references.)
+ //
+ // We can half the number of specializations required by introducing a
+ // function genericTransformTupleBackend(), which is overloaded for each
+ // tuple size and for const and non-const tuple arguments; the functor
+ // argument is always given as as (non-const) reference. When
+ // genericTransformTupleBackend() is called, the type of the Functor template
+ // parameter is the deduced as either "SomeType" or "const SomeType",
+ // depending on whether the function argument is a non-const or a const
+ // lvalue of type "SomeType". As explained above, this does not work for
+ // rvalues (i.e. literals).
+ //
+ // To make it work for literals of functors as well, we wrap the call to
+ // genericTransformTupleBackend() in a function genericTransformTuple().
+ // genericTransformTuple() needs to be overloaded for non-const and const
+ // tuples and functors -- 4 overloads only. Inside genericTransformTuple()
+ // the functor is an lvalue no matter whether the argument was an lvalue or
+ // an rvalue. There is no need need to overload genericTransformTuple() for
+ // all tuple sizes -- this is done by the underlying
+ // genericTransformTupleBackend().
+
+ // genericTransformTupleBackend() is an implementation detail -- hide it
+ // from Doxygen
+#ifndef DOXYGEN
+ // 0-element tuple
+ // This is a special case: we touch neither the tuple nor the functor, so
+ // const references are sufficient and we don't need to overload
+ template<class Functor>
+ typename ForEachType<Functor::template TypeEvaluator,
+ tuple<> >::Type
+ genericTransformTupleBackend
+ (const tuple<>& t, const Functor& f)
+ {
+ return typename ForEachType<Functor::template TypeEvaluator,
+ tuple<> >::Type
+ ();
+ }
+
+ // 1-element tuple
+ template<class T0, class Functor>
+ typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0> >::Type
+ genericTransformTupleBackend
+ (tuple<T0>& t, Functor& f)
+ {
+ return typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0> >::Type
+ (f(get<0>(t)));
+ }
+ template<class T0, class Functor>
+ typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0> >::Type
+ genericTransformTupleBackend
+ (const tuple<T0>& t, Functor& f)
+ {
+ return typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0> >::Type
+ (f(get<0>(t)));
+ }
+
+ // 2-element tuple
+ template<class T0, class T1, class Functor>
+ typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1> >::Type
+ genericTransformTupleBackend
+ (tuple<T0, T1>& t, Functor& f)
+ {
+ return typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1> >::Type
+ (f(get<0>(t)), f(get<1>(t)));
+ }
+ template<class T0, class T1, class Functor>
+ typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1> >::Type
+ genericTransformTupleBackend
+ (const tuple<T0, T1>& t, Functor& f)
+ {
+ return typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1> >::Type
+ (f(get<0>(t)), f(get<1>(t)));
+ }
+
+ // 3-element tuple
+ template<class T0, class T1, class T2, class Functor>
+ typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2> >::Type
+ genericTransformTupleBackend
+ (tuple<T0, T1, T2>& t, Functor& f)
+ {
+ return typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2> >::Type
+ (f(get<0>(t)), f(get<1>(t)), f(get<2>(t)));
+ }
+ template<class T0, class T1, class T2, class Functor>
+ typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2> >::Type
+ genericTransformTupleBackend
+ (const tuple<T0, T1, T2>& t, Functor& f)
+ {
+ return typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2> >::Type
+ (f(get<0>(t)), f(get<1>(t)), f(get<2>(t)));
+ }
+
+ // 4-element tuple
+ template<class T0, class T1, class T2, class T3, class Functor>
+ typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3> >::Type
+ genericTransformTupleBackend
+ (tuple<T0, T1, T2, T3>& t, Functor& f)
+ {
+ return typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3> >::Type
+ (f(get<0>(t)), f(get<1>(t)), f(get<2>(t)), f(get<3>(t)));
+ }
+ template<class T0, class T1, class T2, class T3, class Functor>
+ typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3> >::Type
+ genericTransformTupleBackend
+ (const tuple<T0, T1, T2, T3>& t, Functor& f)
+ {
+ return typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3> >::Type
+ (f(get<0>(t)), f(get<1>(t)), f(get<2>(t)), f(get<3>(t)));
+ }
+
+ // 5-element tuple
+ template<class T0, class T1, class T2, class T3, class T4, class Functor>
+ typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3, T4> >::Type
+ genericTransformTupleBackend
+ (tuple<T0, T1, T2, T3, T4>& t, Functor& f)
+ {
+ return typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3, T4> >::Type
+ (f(get<0>(t)), f(get<1>(t)), f(get<2>(t)), f(get<3>(t)), f(get<4>(t)));
+ }
+ template<class T0, class T1, class T2, class T3, class T4, class Functor>
+ typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3, T4> >::Type
+ genericTransformTupleBackend
+ (const tuple<T0, T1, T2, T3, T4>& t, Functor& f)
+ {
+ return typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3, T4> >::Type
+ (f(get<0>(t)), f(get<1>(t)), f(get<2>(t)), f(get<3>(t)), f(get<4>(t)));
+ }
+
+ // 6-element tuple
+ template<class T0, class T1, class T2, class T3, class T4, class T5,
+ class Functor>
+ typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3, T4, T5> >::Type
+ genericTransformTupleBackend
+ (tuple<T0, T1, T2, T3, T4, T5>& t, Functor& f)
+ {
+ return typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3, T4, T5> >::Type
+ (f(get<0>(t)), f(get<1>(t)), f(get<2>(t)), f(get<3>(t)), f(get<4>(t)),
+ f(get<5>(t)));
+ }
+ template<class T0, class T1, class T2, class T3, class T4, class T5,
+ class Functor>
+ typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3, T4, T5> >::Type
+ genericTransformTupleBackend
+ (const tuple<T0, T1, T2, T3, T4, T5>& t, Functor& f)
+ {
+ return typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3, T4, T5> >::Type
+ (f(get<0>(t)), f(get<1>(t)), f(get<2>(t)), f(get<3>(t)), f(get<4>(t)),
+ f(get<5>(t)));
+ }
+
+ // 7-element tuple
+ template<class T0, class T1, class T2, class T3, class T4, class T5,
+ class T6, class Functor>
+ typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3, T4, T5, T6> >::Type
+ genericTransformTupleBackend
+ (tuple<T0, T1, T2, T3, T4, T5, T6>& t, Functor& f)
+ {
+ return typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3, T4, T5, T6> >::Type
+ (f(get<0>(t)), f(get<1>(t)), f(get<2>(t)), f(get<3>(t)), f(get<4>(t)),
+ f(get<5>(t)), f(get<6>(t)));
+ }
+ template<class T0, class T1, class T2, class T3, class T4, class T5,
+ class T6, class Functor>
+ typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3, T4, T5, T6> >::Type
+ genericTransformTupleBackend
+ (const tuple<T0, T1, T2, T3, T4, T5, T6>& t, Functor& f)
+ {
+ return typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3, T4, T5, T6> >::Type
+ (f(get<0>(t)), f(get<1>(t)), f(get<2>(t)), f(get<3>(t)), f(get<4>(t)),
+ f(get<5>(t)), f(get<6>(t)));
+ }
+
+ // 8-element tuple
+ template<class T0, class T1, class T2, class T3, class T4, class T5,
+ class T6, class T7, class Functor>
+ typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3, T4, T5, T6, T7> >::Type
+ genericTransformTupleBackend
+ (tuple<T0, T1, T2, T3, T4, T5, T6, T7>& t, Functor& f)
+ {
+ return typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3, T4, T5, T6, T7> >::Type
+ (f(get<0>(t)), f(get<1>(t)), f(get<2>(t)), f(get<3>(t)), f(get<4>(t)),
+ f(get<5>(t)), f(get<6>(t)), f(get<7>(t)));
+ }
+ template<class T0, class T1, class T2, class T3, class T4, class T5,
+ class T6, class T7, class Functor>
+ typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3, T4, T5, T6, T7> >::Type
+ genericTransformTupleBackend
+ (const tuple<T0, T1, T2, T3, T4, T5, T6, T7>& t, Functor& f)
+ {
+ return typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3, T4, T5, T6, T7> >::Type
+ (f(get<0>(t)), f(get<1>(t)), f(get<2>(t)), f(get<3>(t)), f(get<4>(t)),
+ f(get<5>(t)), f(get<6>(t)), f(get<7>(t)));
+ }
+
+ // 9-element tuple
+ template<class T0, class T1, class T2, class T3, class T4, class T5,
+ class T6, class T7, class T8, class Functor>
+ typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8> >::Type
+ genericTransformTupleBackend
+ (tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8>& t, Functor& f)
+ {
+ return typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8> >::Type
+ (f(get<0>(t)), f(get<1>(t)), f(get<2>(t)), f(get<3>(t)), f(get<4>(t)),
+ f(get<5>(t)), f(get<6>(t)), f(get<7>(t)), f(get<8>(t)));
+ }
+ template<class T0, class T1, class T2, class T3, class T4, class T5,
+ class T6, class T7, class T8, class Functor>
+ typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8> >::Type
+ genericTransformTupleBackend
+ (const tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8>& t, Functor& f)
+ {
+ return typename ForEachType<Functor::template TypeEvaluator,
+ tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8> >::Type
+ (f(get<0>(t)), f(get<1>(t)), f(get<2>(t)), f(get<3>(t)), f(get<4>(t)),
+ f(get<5>(t)), f(get<6>(t)), f(get<7>(t)), f(get<8>(t)));
+ }
+
+ // // 10-element tuple
+ // template<class T0, class T1, class T2, class T3, class T4, class T5,
+ // class T6, class T7, class T8, class T9, class Functor>
+ // typename ForEachType<Functor::template TypeEvaluator,
+ // tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >::Type
+ // genericTransformTupleBackend
+ // (tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>& t, Functor& f)
+ // {
+ // return typename ForEachType<Functor::template TypeEvaluator,
+ // tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >::Type
+ // (f(get<0>(t)), f(get<1>(t)), f(get<2>(t)), f(get<3>(t)), f(get<4>(t)),
+ // f(get<5>(t)), f(get<6>(t)), f(get<7>(t)), f(get<8>(t)), f(get<9>(t)));
+ // }
+ // template<class T0, class T1, class T2, class T3, class T4, class T5,
+ // class T6, class T7, class T8, class T9, class Functor>
+ // typename ForEachType<Functor::template TypeEvaluator,
+ // tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >::Type
+ // genericTransformTupleBackend
+ // (const tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>& t, Functor& f)
+ // {
+ // return typename ForEachType<Functor::template TypeEvaluator,
+ // tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >::Type
+ // (f(get<0>(t)), f(get<1>(t)), f(get<2>(t)), f(get<3>(t)), f(get<4>(t)),
+ // f(get<5>(t)), f(get<6>(t)), f(get<7>(t)), f(get<8>(t)), f(get<9>(t)));
+ // }
+#endif // ! defined(DOXYGEN)
+
+ //! transform a tuple object into another tuple object
+ /**
+ * \code
+ * #include <dune/common/utility.hh>
+ * \endcode
+ * This function does for the value of a tuple what ForEachType does for the
+ * type of a tuple: it transforms the value using a user-provided policy
+ * functor.
+ *
+ * \param t The tuple value to transform.
+ * \param f The functor to use to transform the values.
+ *
+ * The functor should have the following form:
+ * \code
+ * struct Functor {
+ * template<class> struct TypeEvaluator {
+ * typedef user-defined Type;
+ * };
+ *
+ * template<class T>
+ * typename TypeEvaluator<T>::Type operator()(T& val);
+ *
+ * template<class T>
+ * typename TypeEvaluator<T>::Type operator()(T& val) const;
+ *
+ * template<class T>
+ * typename TypeEvaluator<T>::Type operator()(const T& val);
+ *
+ * template<class T>
+ * typename TypeEvaluator<T>::Type operator()(const T& val) const;
+ * };
+ * \endcode
+ * The member class template \c TypeEvaluator should be a class template
+ * suitable as the \c TypeEvaluator template parameter for ForEachType. The
+ * function call operator \c operator() is used to transform the value; only
+ * the signatures of \c operator() which are actually used must be present.
+ *
+ * There are overloaded definitions of genericTransformTuple() wich take
+ * constant tuple and functor arguments so rvalues are permissible as
+ * arguments here. These overloaded definitions are not documented
+ * separately.
+ */
+ template<class Tuple, class Functor>
+ typename ForEachType<Functor::template TypeEvaluator, Tuple>::Type
+ genericTransformTuple(Tuple& t, Functor& f) {
+ return genericTransformTupleBackend(t, f);
+ }
+#ifndef DOXYGEN
+ template<class Tuple, class Functor>
+ typename ForEachType<Functor::template TypeEvaluator, Tuple>::Type
+ genericTransformTuple(const Tuple& t, Functor& f) {
+ return genericTransformTupleBackend(t, f);
+ }
+ template<class Tuple, class Functor>
+ typename ForEachType<Functor::template TypeEvaluator, Tuple>::Type
+ genericTransformTuple(Tuple& t, const Functor& f) {
+ return genericTransformTupleBackend(t, f);
+ }
+ template<class Tuple, class Functor>
+ typename ForEachType<Functor::template TypeEvaluator, Tuple>::Type
+ genericTransformTuple(const Tuple& t, const Functor& f) {
+ return genericTransformTupleBackend(t, f);
+ }
+#endif // ! defined(DOXYGEN)
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // transformTuple() related stuff
+ //
+
+ //! helper class to implement transformTuple()
+ /**
+ * \tparam TE TypeEvaluator class template.
+ * \tparam An Type of extra arguments to pass to \c TE<T>::apply(). \c void
+ * means "no argument". Only trailing arguments may be void.
+ *
+ * This class stores references to a number of arguments it receives in the
+ * constructor. Later, its function call operator \c operator() may be
+ * called with a parameter \c t of type \c T. \c operator() will then call
+ * the static method \c TE<T>::apply(t,args...), where \c args... is the
+ * sequence of arguments the object was constructed with. \c operator()
+ * will convert the result to type \c TE<T>::Type and return it.
+ *
+ * \c TE should be an extended version of the \c TypeEvaluator class
+ * template parameter of ForEachType, for instance:
+ * \code
+ * template <class T>
+ * struct TypeEvaluator {
+ * typedef T* Type;
+ * static Type apply(T& t, void* a0) {
+ * return t ? &t : static_cast<T*>(a0);
+ * }
+ * };
+ * \endcode
+ * This example is for a TransformTupleFunctor with one argument, i.e. \c
+ * A0!=void and all other \c An=void. For the type transformation, it will
+ * transform a value of some type T into a pointer to T. For the value
+ * transformation, it will take a reference to a value of type T and return
+ * the pointer to that value, unless the value evaluates to false in boolean
+ * context. If the value evaluates to false, it will instead return the
+ * pointer from the extra argument.
+ */
+ template<template<class> class TE, class A0 = void, class A1 = void,
+ class A2 = void, class A3 = void, class A4 = void, class A5 = void,
+ class A6 = void, class A7 = void, class A8 = void, class A9 = void>
+ class TransformTupleFunctor {
+ A0& a0; A1& a1; A2& a2; A3& a3; A4& a4; A5& a5; A6& a6; A7& a7; A8& a8;
+ A9& a9;
+
+ public:
+ //! export the TypeEvaluator template class for genericTransformTuple()
+ template<class T> struct TypeEvaluator : public TE<T> {};
+
+ //! constructor
+ /**
+ * The actual number of arguments varies between specializations, the
+ * actual number of arguments here is equal to the number of non-\c void
+ * class template arguments \c An.
+ */
+ TransformTupleFunctor(A0& a0_, A1& a1_, A2& a2_, A3& a3_, A4& a4_, A5& a5_,
+ A6& a6_, A7& a7_, A8& a8_, A9& a9_)
+ : a0(a0_), a1(a1_), a2(a2_), a3(a3_), a4(a4_), a5(a5_), a6(a6_), a7(a7_),
+ a8(a8_), a9(a9_)
+ { }
+
+ //! call \c TE<T>::apply(t,args...)
+ /**
+ * This calls the static apply method of the TypeEvaluator class
+ * template.
+ *
+ * \note There is no need to overload \c operator() with at \c const \c T&
+ * argument, since genericTransformTuple() will always use an lvalue
+ * argument.
+ */
+ template<class T>
+ typename TE<T>::Type operator()(T& t) const {
+ return TE<T>::apply(t, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+ }
+ };
+
+ //! syntactic sugar for creation of TransformTupleFunctor objects
+ /**
+ * \code
+ * #include <dune/common/utility.hh>
+ * \endcode
+ * \tparam TE TypeEvaluator class template.
+ * \tparam A0 Type of extra arguments to pass to \c TE<T>::apply(). It
+ * should not be necessary to specify these template parameters
+ * explicitly since they can be deduced.
+ * \tparam A1 Type of extra arguments to pass to \c TE<T>::apply(). It
+ * should not be necessary to specify these template parameters
+ * explicitly since they can be deduced.
+ * \tparam A2 Type of extra arguments to pass to \c TE<T>::apply(). It
+ * should not be necessary to specify these template parameters
+ * explicitly since they can be deduced.
+ * \tparam A3 Type of extra arguments to pass to \c TE<T>::apply(). It
+ * should not be necessary to specify these template parameters
+ * explicitly since they can be deduced.
+ * \tparam A4 Type of extra arguments to pass to \c TE<T>::apply(). It
+ * should not be necessary to specify these template parameters
+ * explicitly since they can be deduced.
+ * \tparam A5 Type of extra arguments to pass to \c TE<T>::apply(). It
+ * should not be necessary to specify these template parameters
+ * explicitly since they can be deduced.
+ * \tparam A6 Type of extra arguments to pass to \c TE<T>::apply(). It
+ * should not be necessary to specify these template parameters
+ * explicitly since they can be deduced.
+ * \tparam A7 Type of extra arguments to pass to \c TE<T>::apply(). It
+ * should not be necessary to specify these template parameters
+ * explicitly since they can be deduced.
+ * \tparam A8 Type of extra arguments to pass to \c TE<T>::apply(). It
+ * should not be necessary to specify these template parameters
+ * explicitly since they can be deduced.
+ * \tparam A9 Type of extra arguments to pass to \c TE<T>::apply(). It
+ * should not be necessary to specify these template parameters
+ * explicitly since they can be deduced.
+ *
+ * \param a0 Arguments to save references to in the TransformTupleFunctor.
+ * \param a1 Arguments to save references to in the TransformTupleFunctor.
+ * \param a2 Arguments to save references to in the TransformTupleFunctor.
+ * \param a3 Arguments to save references to in the TransformTupleFunctor.
+ * \param a4 Arguments to save references to in the TransformTupleFunctor.
+ * \param a5 Arguments to save references to in the TransformTupleFunctor.
+ * \param a6 Arguments to save references to in the TransformTupleFunctor.
+ * \param a7 Arguments to save references to in the TransformTupleFunctor.
+ * \param a8 Arguments to save references to in the TransformTupleFunctor.
+ * \param a9 Arguments to save references to in the TransformTupleFunctor.
+ *
+ * There are overloads of this function (not documented separately) for any
+ * number of arguments, up to an implementation-defined arbitrary limit.
+ * The number of arguments given determines the number of non-\c void
+ * template arguments in the type of the returned TransformTupleFunctor.
+ */
+ template<template<class> class TE, class A0, class A1, class A2, class A3,
+ class A4, class A5, class A6, class A7, class A8, class A9>
+ TransformTupleFunctor<TE, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9>
+ makeTransformTupleFunctor(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
+ A6& a6, A7& a7, A8& a8, A9& a9) {
+ return TransformTupleFunctor<TE, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9>
+ (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+ }
+
+#ifndef DOXYGEN
+ // 0 argument
+ template<template<class> class TE>
+ struct TransformTupleFunctor<TE>
+ {
+ template<class T> struct TypeEvaluator : public TE<T> {};
+
+ template<class T>
+ typename TE<T>::Type operator()(T& t) const {
+ return TE<T>::apply(t);
+ }
+ };
+ template<template<class> class TE>
+ TransformTupleFunctor<TE>
+ makeTransformTupleFunctor() {
+ return TransformTupleFunctor<TE>
+ ();
+ }
+
+ // 1 argument
+ template<template<class> class TE, class A0>
+ class TransformTupleFunctor<TE, A0>
+ {
+ A0& a0;
+
+ public:
+ template<class T> struct TypeEvaluator : public TE<T> {};
+
+ TransformTupleFunctor(A0& a0_)
+ : a0(a0_)
+ { }
+
+ template<class T>
+ typename TE<T>::Type operator()(T& t) const {
+ return TE<T>::apply(t, a0);
+ }
+ };
+ template<template<class> class TE, class A0>
+ TransformTupleFunctor<TE, A0>
+ makeTransformTupleFunctor(A0& a0) {
+ return TransformTupleFunctor<TE, A0>
+ (a0);
+ }
+
+ // 2 argument
+ template<template<class> class TE, class A0, class A1>
+ class TransformTupleFunctor<TE, A0, A1>
+ {
+ A0& a0; A1& a1;
+
+ public:
+ template<class T> struct TypeEvaluator : public TE<T> {};
+
+ TransformTupleFunctor(A0& a0_, A1& a1_)
+ : a0(a0_), a1(a1_)
+ { }
+
+ template<class T>
+ typename TE<T>::Type operator()(T& t) const {
+ return TE<T>::apply(t, a0, a1);
+ }
+ };
+ template<template<class> class TE, class A0, class A1>
+ TransformTupleFunctor<TE, A0, A1>
+ makeTransformTupleFunctor(A0& a0, A1& a1) {
+ return TransformTupleFunctor<TE, A0, A1>
+ (a0, a1);
+ }
+
+ // 3 arguments
+ template<template<class> class TE, class A0, class A1, class A2>
+ class TransformTupleFunctor<TE, A0, A1, A2>
+ {
+ A0& a0; A1& a1; A2& a2;
+
+ public:
+ template<class T> struct TypeEvaluator : public TE<T> {};
+
+ TransformTupleFunctor(A0& a0_, A1& a1_, A2& a2_)
+ : a0(a0_), a1(a1_), a2(a2_)
+ { }
+
+ template<class T>
+ typename TE<T>::Type operator()(T& t) const {
+ return TE<T>::apply(t, a0, a1, a2);
+ }
+ };
+ template<template<class> class TE, class A0, class A1, class A2>
+ TransformTupleFunctor<TE, A0, A1, A2>
+ makeTransformTupleFunctor(A0& a0, A1& a1, A2& a2) {
+ return TransformTupleFunctor<TE, A0, A1, A2>
+ (a0, a1, a2);
+ }
+
+ // 4 arguments
+ template<template<class> class TE, class A0, class A1, class A2, class A3>
+ class TransformTupleFunctor<TE, A0, A1, A2, A3>
+ {
+ A0& a0; A1& a1; A2& a2; A3& a3;
+
+ public:
+ template<class T> struct TypeEvaluator : public TE<T> {};
+
+ TransformTupleFunctor(A0& a0_, A1& a1_, A2& a2_, A3& a3_)
+ : a0(a0_), a1(a1_), a2(a2_), a3(a3_)
+ { }
+
+ template<class T>
+ typename TE<T>::Type operator()(T& t) const {
+ return TE<T>::apply(t, a0, a1, a2, a3);
+ }
+ };
+ template<template<class> class TE, class A0, class A1, class A2, class A3>
+ TransformTupleFunctor<TE, A0, A1, A2, A3>
+ makeTransformTupleFunctor(A0& a0, A1& a1, A2& a2, A3& a3) {
+ return TransformTupleFunctor<TE, A0, A1, A2, A3>
+ (a0, a1, a2, a3);
+ }
+
+ // 5 arguments
+ template<template<class> class TE, class A0, class A1, class A2, class A3,
+ class A4>
+ class TransformTupleFunctor<TE, A0, A1, A2, A3, A4>
+ {
+ A0& a0; A1& a1; A2& a2; A3& a3; A4& a4;
+
+ public:
+ template<class T> struct TypeEvaluator : public TE<T> {};
+
+ TransformTupleFunctor(A0& a0_, A1& a1_, A2& a2_, A3& a3_, A4& a4_)
+ : a0(a0_), a1(a1_), a2(a2_), a3(a3_), a4(a4_)
+ { }
+
+ template<class T>
+ typename TE<T>::Type operator()(T& t) const {
+ return TE<T>::apply(t, a0, a1, a2, a3, a4);
+ }
+ };
+ template<template<class> class TE, class A0, class A1, class A2, class A3,
+ class A4>
+ TransformTupleFunctor<TE, A0, A1, A2, A3, A4>
+ makeTransformTupleFunctor(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4) {
+ return TransformTupleFunctor<TE, A0, A1, A2, A3, A4>
+ (a0, a1, a2, a3, a4);
+ }
+
+ // 6 arguments
+ template<template<class> class TE, class A0, class A1, class A2, class A3,
+ class A4, class A5>
+ class TransformTupleFunctor<TE, A0, A1, A2, A3, A4, A5>
+ {
+ A0& a0; A1& a1; A2& a2; A3& a3; A4& a4; A5& a5;
+
+ public:
+ template<class T> struct TypeEvaluator : public TE<T> {};
+
+ TransformTupleFunctor(A0& a0_, A1& a1_, A2& a2_, A3& a3_, A4& a4_, A5& a5_)
+ : a0(a0_), a1(a1_), a2(a2_), a3(a3_), a4(a4_), a5(a5_)
+ { }
+
+ template<class T>
+ typename TE<T>::Type operator()(T& t) const {
+ return TE<T>::apply(t, a0, a1, a2, a3, a4, a5);
+ }
+ };
+ template<template<class> class TE, class A0, class A1, class A2, class A3,
+ class A4, class A5>
+ TransformTupleFunctor<TE, A0, A1, A2, A3, A4, A5>
+ makeTransformTupleFunctor(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5) {
+ return TransformTupleFunctor<TE, A0, A1, A2, A3, A4, A5>
+ (a0, a1, a2, a3, a4, a5);
+ }
+
+ // 7 arguments
+ template<template<class> class TE, class A0, class A1, class A2, class A3,
+ class A4, class A5, class A6>
+ class TransformTupleFunctor<TE, A0, A1, A2, A3, A4, A5, A6>
+ {
+ A0& a0; A1& a1; A2& a2; A3& a3; A4& a4; A5& a5; A6& a6;
+
+ public:
+ template<class T> struct TypeEvaluator : public TE<T> {};
+
+ TransformTupleFunctor(A0& a0_, A1& a1_, A2& a2_, A3& a3_, A4& a4_, A5& a5_,
+ A6& a6_)
+ : a0(a0_), a1(a1_), a2(a2_), a3(a3_), a4(a4_), a5(a5_), a6(a6_)
+ { }
+
+ template<class T>
+ typename TE<T>::Type operator()(T& t) const {
+ return TE<T>::apply(t, a0, a1, a2, a3, a4, a5, a6);
+ }
+ };
+ template<template<class> class TE, class A0, class A1, class A2, class A3,
+ class A4, class A5, class A6>
+ TransformTupleFunctor<TE, A0, A1, A2, A3, A4, A5, A6>
+ makeTransformTupleFunctor(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
+ A6& a6) {
+ return TransformTupleFunctor<TE, A0, A1, A2, A3, A4, A5, A6>
+ (a0, a1, a2, a3, a4, a5, a6);
+ }
+
+ // 8 arguments
+ template<template<class> class TE, class A0, class A1, class A2, class A3,
+ class A4, class A5, class A6, class A7>
+ class TransformTupleFunctor<TE, A0, A1, A2, A3, A4, A5, A6, A7>
+ {
+ A0& a0; A1& a1; A2& a2; A3& a3; A4& a4; A5& a5; A6& a6; A7& a7;
+
+ public:
+ template<class T> struct TypeEvaluator : public TE<T> {};
+
+ TransformTupleFunctor(A0& a0_, A1& a1_, A2& a2_, A3& a3_, A4& a4_, A5& a5_,
+ A6& a6_, A7& a7_)
+ : a0(a0_), a1(a1_), a2(a2_), a3(a3_), a4(a4_), a5(a5_), a6(a6_), a7(a7_)
+ { }
+
+ template<class T>
+ typename TE<T>::Type operator()(T& t) const {
+ return TE<T>::apply(t, a0, a1, a2, a3, a4, a5, a6, a7);
+ }
+ };
+ template<template<class> class TE, class A0, class A1, class A2, class A3,
+ class A4, class A5, class A6, class A7>
+ TransformTupleFunctor<TE, A0, A1, A2, A3, A4, A5, A6, A7>
+ makeTransformTupleFunctor(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
+ A6& a6, A7& a7) {
+ return TransformTupleFunctor<TE, A0, A1, A2, A3, A4, A5, A6, A7>
+ (a0, a1, a2, a3, a4, a5, a6, a7);
+ }
+
+ // 9 arguments
+ template<template<class> class TE, class A0, class A1, class A2, class A3,
+ class A4, class A5, class A6, class A7, class A8>
+ class TransformTupleFunctor<TE, A0, A1, A2, A3, A4, A5, A6, A7, A8>
+ {
+ A0& a0; A1& a1; A2& a2; A3& a3; A4& a4; A5& a5; A6& a6; A7& a7; A8& a8;
+
+ public:
+ template<class T> struct TypeEvaluator : public TE<T> {};
+
+ TransformTupleFunctor(A0& a0_, A1& a1_, A2& a2_, A3& a3_, A4& a4_, A5& a5_,
+ A6& a6_, A7& a7_, A8& a8_)
+ : a0(a0_), a1(a1_), a2(a2_), a3(a3_), a4(a4_), a5(a5_), a6(a6_), a7(a7_),
+ a8(a8_)
+ { }
+
+ template<class T>
+ typename TE<T>::Type operator()(T& t) const {
+ return TE<T>::apply(t, a0, a1, a2, a3, a4, a5, a6, a7, a8);
+ }
+ };
+ template<template<class> class TE, class A0, class A1, class A2, class A3,
+ class A4, class A5, class A6, class A7, class A8>
+ TransformTupleFunctor<TE, A0, A1, A2, A3, A4, A5, A6, A7, A8>
+ makeTransformTupleFunctor(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
+ A6& a6, A7& a7, A8& a8) {
+ return TransformTupleFunctor<TE, A0, A1, A2, A3, A4, A5, A6, A7, A8>
+ (a0, a1, a2, a3, a4, a5, a6, a7, a8);
+ }
+#endif // ! defined(DOXYGEN)
+
+ //! transform a tuple's value according to a user-supplied policy
+ /**
+ * \code
+ * #include <dune/common/utility.hh>
+ * \endcode
+ * This function provides functionality similiar to genericTransformTuple(),
+ * although less general and closer in spirit to ForEachType.
+ *
+ * \tparam TypeEvaluator Used as the \c TE template argument to
+ * TransformTupleFunctor internally.
+ * \tparam Tuple Type of the tuple to transform.
+ * \tparam A0 Types of extra argument to call the transformation
+ * function with.
+ * \tparam A1 Types of extra argument to call the transformation
+ * function with.
+ * \tparam A2 Types of extra argument to call the transformation
+ * function with.
+ * \tparam A3 Types of extra argument to call the transformation
+ * function with.
+ * \tparam A4 Types of extra argument to call the transformation
+ * function with.
+ * \tparam A5 Types of extra argument to call the transformation
+ * function with.
+ * \tparam A6 Types of extra argument to call the transformation
+ * function with.
+ * \tparam A7 Types of extra argument to call the transformation
+ * function with.
+ * \tparam A8 Types of extra argument to call the transformation
+ * function with.
+ * \tparam A9 Types of extra argument to call the transformation
+ * function with.
+ *
+ * \note The \c Tuple and \c An template arguments can be deduced from the
+ * function arguments, so they can usually be omitted.
+ *
+ * \param orig Tuple value to be transformed.
+ * \param a0 Extra argument values to provide to the transformation
+ * function.
+ * \param a1 Extra argument values to provide to the transformation
+ * function.
+ * \param a2 Extra argument values to provide to the transformation
+ * function.
+ * \param a3 Extra argument values to provide to the transformation
+ * function.
+ * \param a4 Extra argument values to provide to the transformation
+ * function.
+ * \param a5 Extra argument values to provide to the transformation
+ * function.
+ * \param a6 Extra argument values to provide to the transformation
+ * function.
+ * \param a7 Extra argument values to provide to the transformation
+ * function.
+ * \param a8 Extra argument values to provide to the transformation
+ * function.
+ * \param a9 Extra argument values to provide to the transformation
+ * function.
+ *
+ * This function is overloaded for any number of extra arguments, up to an
+ * implementation-defined arbitrary limit. The overloads are not documented
+ * separately.
+ *
+ * The \c TypeEvaluator class template should be suitable as the \c TE
+ * template argument for TransformTupleFunctor. It has the following form
+ * (an extension of the \c TypeEvaluator template argument of ForEachType):
+ * \code
+ * template <class T>
+ * struct TypeEvaluator {
+ * typedef UserDefined Type;
+ *
+ * template<class A0, class A1, class A2, class A3, class A4, class A5,
+ * class A6, class A7, class A8, class A9>
+ * static Type apply(T& t, A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
+ * A6& a6, A7& a7, A8& a8, A9& a9);
+ * };
+ * \endcode
+ * For any given element type \c T of the tuple, the TypeEvaluator template
+ * class should provide a member typedef \c Type which determines the type
+ * of the transformed value and a static function \c apply(), taking the
+ * value of the tuple element \c t and the extra arguments given to
+ * transformTuple(). The signature of \c apply() does not have to match the
+ * one given above exactly, as long as it can be called that way.
+ *
+ * \note Since transformTuple() takes non-const references to the extra
+ * arguments, it will only bind to lvalue extra arguments, unless you
+ * specify the corresponding template parameter as \c const \c
+ * SomeType. Specifically this means that you cannot simply use
+ * literals or function return values as extra arguments. Providing
+ * overloads for all possible combinations of rvalue and lvalue extra
+ * arguments would result in \f$2^{n+1}-1\f$ overloads where \f$n\f$
+ * is the implementation defined limit in the number of extra
+ * arguments.
+ *
+ * \sa genericTransforTuple(), ForEachType, AddRefTypeEvaluator, and
+ * AddPtrTypeEvaluator.
+ */
+ template<template<class> class TypeEvaluator, class Tuple, class A0,
+ class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8, class A9>
+ typename remove_const<typename ForEachType<TypeEvaluator, Tuple>::Type>::type
+ transformTuple(Tuple& orig, A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
+ A6& a6, A7& a7, A8& a8, A9& a9) {
+ return genericTransformTuple
+ ( orig,
+ makeTransformTupleFunctor<TypeEvaluator>(a0, a1, a2, a3, a4, a5, a6,
+ a7, a8, a9));
+ }
+
+#ifndef DOXYGEN
+ // 0 extra arguments
+ template<template<class> class TypeEvaluator, class Tuple>
+ typename remove_const<typename ForEachType<TypeEvaluator, Tuple>::Type>::type
+ transformTuple(Tuple& orig) {
+ return genericTransformTuple
+ ( orig,
+ makeTransformTupleFunctor<TypeEvaluator>());
+ }
+
+ // 1 extra argument
+ template<template<class> class TypeEvaluator, class Tuple, class A0>
+ typename remove_const<typename ForEachType<TypeEvaluator, Tuple>::Type>::type
+ transformTuple(Tuple& orig, A0& a0) {
+ return genericTransformTuple
+ ( orig,
+ makeTransformTupleFunctor<TypeEvaluator>(a0));
+ }
+
+ // 2 extra arguments
+ template<template<class> class TypeEvaluator, class Tuple, class A0,
+ class A1>
+ typename remove_const<typename ForEachType<TypeEvaluator, Tuple>::Type>::type
+ transformTuple(Tuple& orig, A0& a0, A1& a1) {
+ return genericTransformTuple
+ ( orig,
+ makeTransformTupleFunctor<TypeEvaluator>(a0, a1));
+ }
+
+ // 3 extra arguments
+ template<template<class> class TypeEvaluator, class Tuple, class A0,
+ class A1, class A2>
+ typename remove_const<typename ForEachType<TypeEvaluator, Tuple>::Type>::type
+ transformTuple(Tuple& orig, A0& a0, A1& a1, A2& a2) {
+ return genericTransformTuple
+ ( orig,
+ makeTransformTupleFunctor<TypeEvaluator>(a0, a1, a2));
+ }
+
+ // 4 extra arguments
+ template<template<class> class TypeEvaluator, class Tuple, class A0,
+ class A1, class A2, class A3>
+ typename remove_const<typename ForEachType<TypeEvaluator, Tuple>::Type>::type
+ transformTuple(Tuple& orig, A0& a0, A1& a1, A2& a2, A3& a3) {
+ return genericTransformTuple
+ ( orig,
+ makeTransformTupleFunctor<TypeEvaluator>(a0, a1, a2, a3));
+ }
+
+ // 5 extra arguments
+ template<template<class> class TypeEvaluator, class Tuple, class A0,
+ class A1, class A2, class A3, class A4>
+ typename remove_const<typename ForEachType<TypeEvaluator, Tuple>::Type>::type
+ transformTuple(Tuple& orig, A0& a0, A1& a1, A2& a2, A3& a3, A4& a4) {
+ return genericTransformTuple
+ ( orig,
+ makeTransformTupleFunctor<TypeEvaluator>(a0, a1, a2, a3, a4));
+ }
+
+ // 6 extra arguments
+ template<template<class> class TypeEvaluator, class Tuple, class A0,
+ class A1, class A2, class A3, class A4, class A5>
+ typename remove_const<typename ForEachType<TypeEvaluator, Tuple>::Type>::type
+ transformTuple(Tuple& orig, A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5) {
+ return genericTransformTuple
+ ( orig,
+ makeTransformTupleFunctor<TypeEvaluator>(a0, a1, a2, a3, a4, a5));
+ }
+
+ // 7 extra arguments
+ template<template<class> class TypeEvaluator, class Tuple, class A0,
+ class A1, class A2, class A3, class A4, class A5, class A6>
+ typename remove_const<typename ForEachType<TypeEvaluator, Tuple>::Type>::type
+ transformTuple(Tuple& orig, A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
+ A6& a6) {
+ return genericTransformTuple
+ ( orig,
+ makeTransformTupleFunctor<TypeEvaluator>(a0, a1, a2, a3, a4, a5, a6));
+ }
+
+ // 8 extra arguments
+ template<template<class> class TypeEvaluator, class Tuple, class A0,
+ class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7>
+ typename remove_const<typename ForEachType<TypeEvaluator, Tuple>::Type>::type
+ transformTuple(Tuple& orig, A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
+ A6& a6, A7& a7) {
+ return genericTransformTuple
+ ( orig,
+ makeTransformTupleFunctor<TypeEvaluator>(a0, a1, a2, a3, a4, a5, a6,
+ a7));
+ }
+
+ // 9 extra arguments
+ template<template<class> class TypeEvaluator, class Tuple, class A0,
+ class A1, class A2, class A3, class A4, class A5, class A6,
+ class A7, class A8>
+ typename remove_const<typename ForEachType<TypeEvaluator, Tuple>::Type>::type
+ transformTuple(Tuple& orig, A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
+ A6& a6, A7& a7, A8& a8) {
+ return genericTransformTuple
+ ( orig,
+ makeTransformTupleFunctor<TypeEvaluator>(a0, a1, a2, a3, a4, a5, a6,
+ a7, a8));
+ }
+#endif // not defined(DOXYGEN)
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Sample TypeEvaluators
+ //
+
+ //! \c TypeEvaluator to turn a type \c T into a reference to \c T
+ /**
+ * This is suitable as the \c TypeEvaluator template parameter for
+ * ForEachType and transformTuple().
+ */
+ template<class T>
+ struct AddRefTypeEvaluator {
+ typedef T& Type;
+ static Type apply(T& t) { return t; }
+ };
+
+ //! \c TypeEvaluator to turn a type \c T into a pointer to \c T
+ /**
+ * This is suitable as the \c TypeEvaluator template parameter for
+ * ForEachType and transformTuple().
+ */
+ template<class T>
+ struct AddPtrTypeEvaluator {
+ typedef typename remove_reference<T>::type* Type;
+ static Type apply(T& t) { return &t; }
+ };
+
+ // Specialization, in case the type is already a reference
+ template<class T>
+ struct AddPtrTypeEvaluator<T&> {
+ typedef typename remove_reference<T>::type* Type;
+ static Type apply(T& t) { return &t; }
+ };
+
+ namespace
+ {
+ template<int i, typename T1,typename F>
+ struct Visitor
+ {
+ static inline void visit(F& func, T1& t1)
+ {
+ func.visit(get<tuple_size<T1>::value-i>(t1));
+ Visitor<i-1,T1,F>::visit(func, t1);
+ }
+ };
+
+ template<typename T1,typename F>
+ struct Visitor<0,T1,F>
+ {
+ static inline void visit(F&, T1&)
+ {}
+ };
+
+ template<int i, typename T1, typename T2,typename F>
+ struct PairVisitor
+ {
+ static inline void visit(F& func, T1& t1, T2& t2)
+ {
+ func.visit(get<tuple_size<T1>::value-i>(t1), get<tuple_size<T2>::value-i>(t2));
+ PairVisitor<i-1,T1,T2,F>::visit(func, t1, t2);
+ }
+ };
+
+ template<typename T1, typename T2, typename F>
+ struct PairVisitor<0,T1,T2,F>
+ {
+ static inline void visit(F&, T1&, T2&)
+ {}
+ };
+ }
+
+ /**
+ * @brief Helper template which implements iteration over all storage
+ * elements in a tuple.
+ *
+ * Compile-time constructs that allows to process all elements in a tuple.
+ * The exact operation performed on an element is defined by a function
+ * object, which needs to implement a visit method which is applicable to
+ * all storage elements of a tuple. Each tuple element is visited once, and
+ * the iteration is done in ascending order.
+ *
+ * The following example implements a function object which counts the
+ * elements in a tuple
+ * \code
+ * template <class T>
+ * struct Counter {
+ * Counter() : result_(0) {}
+ *
+ * template <class T>
+ * void visit(T& elem) { ++result_; }
+ *
+ * int result_;
+ * };
+ * \endcode
+ * The number of elements in the tuple are stored in the member variable
+ * result_. The Counter can be used as follows, assuming a tuple t of type
+ * MyTuple is given:
+ * \code
+ * Counter c;
+ * ForEachValue<MyTuple> forEach(t);
+ *
+ * forEach.apply(c);
+ * std::cout << "Number of elements is: " << c.result_ << std::endl;
+ * \endcode
+ */
+ template <class TupleType>
+ class ForEachValue {
+ public:
+ //! \brief Constructor
+ //! \param tuple The tuple which we want to process.
+ ForEachValue(TupleType& tuple) : tuple_(tuple) {}
+
+ //! \brief Applies a function object to each storage element of the tuple.
+ //! \param f Function object.
+ template <class Functor>
+ void apply(Functor& f) const {
+ Visitor<tuple_size<TupleType>::value,TupleType,Functor>::visit(f, tuple_);
+ }
+ private:
+ TupleType& tuple_;
+ };
+
+ //- Definition ForEachValuePair class
+ // Assertion: both tuples have the same length and the contained types are
+ // compatible in the sense of the applied function object
+ /**
+ * @brief Extension of ForEachValue to two tuples...
+ *
+ * This class provides the framework to process two tuples at once. It works
+ * the same as ForEachValue, just that the corresponding function object
+ * takes one argument from the first tuple and one argument from the second.
+ *
+ * \note You have to ensure that the two tuples you provide are compatible
+ * in the sense that they have the same length and that the objects passed
+ * to the function objects are related in meaningful way. The best way to
+ * enforce it is to build the second tuple from the existing first tuple
+ * using ForEachType.
+ */
+ template <class TupleType1, class TupleType2>
+ class ForEachValuePair {
+ public:
+ //! Constructor
+ //! \param t1 First tuple.
+ //! \param t2 Second tuple.
+ ForEachValuePair(TupleType1& t1, TupleType2& t2) :
+ tuple1_(t1),
+ tuple2_(t2)
+ {}
+
+ //! Applies the function object f to the pair of tuples.
+ //! \param f The function object to apply on the pair of tuples.
+ template <class Functor>
+ void apply(Functor& f) {
+ PairVisitor<tuple_size<TupleType1>::value,TupleType1,TupleType2,Functor>
+ ::visit(f, tuple1_, tuple2_);
+ }
+ private:
+ TupleType1& tuple1_;
+ TupleType2& tuple2_;
+ };
+
+ //- Reverse element access
+ /**
+ * @brief Type for reverse element access.
+ *
+ * Counterpart to ElementType for reverse element access.
+ */
+ template <int N, class Tuple>
+ struct AtType {
+ typedef typename tuple_element<tuple_size<Tuple>::value - N - 1,
+ Tuple>::type Type;
+ };
+
+ /**
+ * @brief Reverse element access.
+ *
+ * While Element<...> gives you the arguments beginning at the front of a
+ * tuple, At<...> starts at the end, which may be more convenient, depending
+ * on how you built your tuple.
+ */
+ template <int N>
+ struct At
+ {
+
+ template<typename Tuple>
+ static
+ typename TupleAccessTraits<typename AtType<N, Tuple>::Type>::NonConstType
+ get(Tuple& t)
+ {
+ return Dune::get<tuple_size<Tuple>::value - N - 1>(t);
+ }
+
+ template<typename Tuple>
+ static
+ typename TupleAccessTraits<typename AtType<N, Tuple>::Type>::ConstType
+ get(const Tuple& t)
+ {
+ return Dune::get<tuple_size<Tuple>::value - N - 1>(t);
+ }
+ };
+
+ /**
+ * @brief Deletes all objects pointed to in a tuple of pointers.
+ *
+ * \warning Pointers cannot be set to NULL, so calling the Deletor twice
+ * or accessing elements of a deleted tuple leads to unforeseeable results!
+ */
+ template <class Tuple>
+ class PointerPairDeletor
+ {
+ struct Deletor {
+ template<typename P> void visit(const P& p) { delete p; }
+ };
+
+ public:
+ static void apply(Tuple& t) {
+ static Deletor deletor;
+ ForEachValue<Tuple>(t).apply(deletor);
+ }
+ };
+
+
+ /**
+ * @brief Finding the index of a certain type in a tuple
+ *
+ * \tparam Tuple The tuple type to search in.
+ * \tparam Predicate Predicate which tells FirstPredicateIndex which types
+ * in Tuple to accept. This should be a class template
+ * taking a single type template argument. When
+ * instantiated, it should contain a static member
+ * constant \c value which should be convertible to bool.
+ * A type is accepted if \c value is \c true, otherwise it
+ * is rejected and the next type is tried. Look at IsType
+ * for a sample implementation.
+ * \tparam start First index to try. This can be adjusted to skip
+ * leading tuple elements.
+ * \tparam size This parameter is an implementation detail and should
+ * not be adjusted by the users of this class. It should
+ * always be equal to the size of the tuple.
+ *
+ * This class can search for a type in tuple. It will apply the predicate
+ * to each type in tuple in turn, and set its member constant \c value to
+ * the index of the first type that was accepted by the predicate. If none
+ * of the types are accepted by the predicate, a static_assert is triggered.
+ */
+ template<class Tuple, template<class> class Predicate, std::size_t start = 0,
+ std::size_t size = tuple_size<Tuple>::value>
+ class FirstPredicateIndex :
+ public conditional<Predicate<typename tuple_element<start,
+ Tuple>::type>::value,
+ integral_constant<std::size_t, start>,
+ FirstPredicateIndex<Tuple, Predicate, start+1> >::type
+ {
+ dune_static_assert(tuple_size<Tuple>::value == size, "The \"size\" "
+ "template parameter of FirstPredicateIndex is an "
+ "implementation detail and should never be set "
+ "explicitly!");
+ };
+
+#ifndef DOXYGEN
+ template<class Tuple, template<class> class Predicate, std::size_t size>
+ class FirstPredicateIndex<Tuple, Predicate, size, size>
+ {
+ dune_static_assert(AlwaysFalse<Tuple>::value, "None of the tuple element "
+ "types matches the predicate!");
+ };
+#endif // !DOXYGEN
+
+ /**
+ * @brief Generator for predicates accepting one particular type
+ *
+ * \tparam T The type to accept.
+ *
+ * The generated predicate class is useful together with
+ * FirstPredicateIndex. It will accept exactly the type that is given as
+ * the \c T template parameter.
+ */
+ template<class T>
+ struct IsType {
+ //! @brief The actual predicate
+ template<class U>
+ struct Predicate : public is_same<T, U> {};
+ };
+
+ /**
+ * @brief Find the first occurance of a type in a tuple
+ *
+ * \tparam Tuple The tuple type to search in.
+ * \tparam T Type to search for.
+ * \tparam start First index to try. This can be adjusted to skip leading
+ * tuple elements.
+ *
+ * This class can search for a particular type in tuple. It will check each
+ * type in the tuple in turn, and set its member constant \c value to the
+ * index of the first occurance of type was found. If the type was not
+ * found, a static_assert is triggered.
+ */
+ template<class Tuple, class T, std::size_t start = 0>
+ struct FirstTypeIndex :
+ public FirstPredicateIndex<Tuple, IsType<T>::template Predicate, start>
+ { };
+
+
+
+ /**
+ * \brief Helper template to append a type to a tuple
+ *
+ * \tparam Tuple The tuple type to extend
+ * \tparam T The type to be appended to the tuple
+ */
+ template< class Tuple, class T>
+ struct PushBackTuple
+ {
+ dune_static_assert(AlwaysFalse<Tuple>::value, "Attempt to use the "
+ "unspecialized version of PushBackTuple. "
+ "PushBackTuple needs to be specialized for "
+ "each possible tuple size. Naturally the number of "
+ "pre-defined specializations is limited arbitrarily. "
+ "Maybe you need to raise this limit by defining some "
+ "more specializations?");
+
+ /**
+ * \brief For all specializations this is the type of a tuple with T appended.
+ *
+ * Suppose you have Tuple=tuple<T1, T2, ..., TN> then
+ * this type is tuple<T1, T2, ..., TN, T>.
+ */
+ typedef Tuple type;
+ };
+
+
+#ifndef DOXYGEN
+
+#if HAVE_VARIADIC_TEMPLATES
+ template<class... TupleArgs, class T>
+ struct PushBackTuple<typename Dune::tuple<TupleArgs...>, T>
+ {
+ typedef typename Dune::tuple<TupleArgs..., T> type;
+ };
+#else
+ template<class T>
+ struct PushBackTuple< Dune::tuple<>, T>
+ {
+ typedef typename Dune::tuple<T> type;
+ };
+
+ template< class T1, class T>
+ struct PushBackTuple< Dune::tuple<T1>, T>
+ {
+ typedef typename Dune::tuple<T1, T> type;
+ };
+
+ template< class T1, class T2, class T>
+ struct PushBackTuple< Dune::tuple<T1, T2>, T>
+ {
+ typedef typename Dune::tuple<T1, T2, T> type;
+ };
+
+ template< class T1, class T2, class T3, class T>
+ struct PushBackTuple< Dune::tuple<T1, T2, T3>, T>
+ {
+ typedef typename Dune::tuple<T1, T2, T3, T> type;
+ };
+
+ template< class T1, class T2, class T3, class T4, class T>
+ struct PushBackTuple< Dune::tuple<T1, T2, T3, T4>, T>
+ {
+ typedef typename Dune::tuple<T1, T2, T3, T4, T> type;
+ };
+
+ template< class T1, class T2, class T3, class T4, class T5, class T>
+ struct PushBackTuple< Dune::tuple<T1, T2, T3, T4, T5>, T>
+ {
+ typedef typename Dune::tuple<T1, T2, T3, T4, T5, T> type;
+ };
+
+ template< class T1, class T2, class T3, class T4, class T5, class T6, class T>
+ struct PushBackTuple< Dune::tuple<T1, T2, T3, T4, T5, T6>, T>
+ {
+ typedef typename Dune::tuple<T1, T2, T3, T4, T5, T6, T> type;
+ };
+
+ template< class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T>
+ struct PushBackTuple< Dune::tuple<T1, T2, T3, T4, T5, T6, T7>, T>
+ {
+ typedef typename Dune::tuple<T1, T2, T3, T4, T5, T6, T7, T> type;
+ };
+
+ template< class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T>
+ struct PushBackTuple< Dune::tuple<T1, T2, T3, T4, T5, T6, T7, T8>, T>
+ {
+ typedef typename Dune::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T> type;
+ };
+#endif // HAVE_VARIADIC_TEMPLATES
+
+#endif
+
+
+
+ /**
+ * \brief Helper template to prepend a type to a tuple
+ *
+ * \tparam Tuple The tuple type to extend
+ * \tparam T The type to be prepended to the tuple
+ */
+ template< class Tuple, class T>
+ struct PushFrontTuple
+ {
+ dune_static_assert(AlwaysFalse<Tuple>::value, "Attempt to use the "
+ "unspecialized version of PushFrontTuple. "
+ "PushFrontTuple needs to be specialized for "
+ "each possible tuple size. Naturally the number of "
+ "pre-defined specializations is limited arbitrarily. "
+ "Maybe you need to raise this limit by defining some "
+ "more specializations?");
+
+ /**
+ * \brief For all specializations this is the type of a tuple with T prepended.
+ *
+ * Suppose you have Tuple=tuple<T1, T2, ..., TN> then
+ * this type is tuple<T, T1, T2, ..., TN>.
+ */
+ typedef Tuple type;
+ };
+
+
+#ifndef DOXYGEN
+
+#if HAVE_VARIADIC_TEMPLATES
+ template<class... TupleArgs, class T>
+ struct PushFrontTuple<typename Dune::tuple<TupleArgs...>, T>
+ {
+ typedef typename Dune::tuple<T, TupleArgs...> type;
+ };
+#else
+ template<class T>
+ struct PushFrontTuple< Dune::tuple<>, T>
+ {
+ typedef typename Dune::tuple<T> type;
+ };
+
+ template< class T1, class T>
+ struct PushFrontTuple< Dune::tuple<T1>, T>
+ {
+ typedef typename Dune::tuple<T, T1> type;
+ };
+
+ template< class T1, class T2, class T>
+ struct PushFrontTuple< Dune::tuple<T1, T2>, T>
+ {
+ typedef typename Dune::tuple<T, T1, T2> type;
+ };
+
+ template< class T1, class T2, class T3, class T>
+ struct PushFrontTuple< Dune::tuple<T1, T2, T3>, T>
+ {
+ typedef typename Dune::tuple<T, T1, T2, T3> type;
+ };
+
+ template< class T1, class T2, class T3, class T4, class T>
+ struct PushFrontTuple< Dune::tuple<T1, T2, T3, T4>, T>
+ {
+ typedef typename Dune::tuple<T, T1, T2, T3, T4> type;
+ };
+
+ template< class T1, class T2, class T3, class T4, class T5, class T>
+ struct PushFrontTuple< Dune::tuple<T1, T2, T3, T4, T5>, T>
+ {
+ typedef typename Dune::tuple<T, T1, T2, T3, T4, T5> type;
+ };
+
+ template< class T1, class T2, class T3, class T4, class T5, class T6, class T>
+ struct PushFrontTuple< Dune::tuple<T1, T2, T3, T4, T5, T6>, T>
+ {
+ typedef typename Dune::tuple<T, T1, T2, T3, T4, T5, T6> type;
+ };
+
+ template< class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T>
+ struct PushFrontTuple< Dune::tuple<T1, T2, T3, T4, T5, T6, T7>, T>
+ {
+ typedef typename Dune::tuple<T, T1, T2, T3, T4, T5, T6, T7> type;
+ };
+
+ template< class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T>
+ struct PushFrontTuple< Dune::tuple<T1, T2, T3, T4, T5, T6, T7, T8>, T>
+ {
+ typedef typename Dune::tuple<T, T1, T2, T3, T4, T5, T6, T7, T8> type;
+ };
+#endif // HAVE_VARIADIC_TEMPLATES
+
+#endif
+
+
+
+ /**
+ * \brief Apply reduce with meta binary function to template
+ *
+ * For a tuple\<T0,T1,...,TN-1,TN,...\> the exported result is
+ *
+ * F\< ... F\< F\< F\<Seed,T0\>\::type, T1\>\::type, T2\>\::type, ... TN-1\>\::type
+ *
+ * \tparam F Binary meta function
+ * \tparam Tuple Apply reduce operation to this tuple
+ * \tparam Seed Initial value for reduce operation
+ * \tparam N Reduce the first N tuple elements
+ */
+ template<
+ template <class, class> class F,
+ class Tuple,
+ class Seed=tuple<>,
+ int N=tuple_size<Tuple>::value>
+ struct ReduceTuple
+ {
+ typedef typename ReduceTuple<F, Tuple, Seed, N-1>::type Accumulated;
+ typedef typename tuple_element<N-1, Tuple>::type Value;
+
+ //! Result of the reduce operation
+ typedef typename F<Accumulated, Value>::type type;
+ };
+
+ /**
+ * \brief Apply reduce with meta binary function to template
+ *
+ * Specialization for reduction of 0 elements.
+ * The exported result type is Seed.
+ *
+ * \tparam F Binary meta function
+ * \tparam Tuple Apply reduce operation to this tuple
+ * \tparam Seed Initial value for reduce operation
+ */
+ template<
+ template <class, class> class F,
+ class Tuple,
+ class Seed>
+ struct ReduceTuple<F, Tuple, Seed, 0>
+ {
+ //! Result of the reduce operation
+ typedef Seed type;
+ };
+
+
+
+ /**
+ * \brief Join two tuples
+ *
+ * For Head=tuple<T0,...,TN> and Tail=tuple<S0,...,SM>
+ * the exported result is tuple<T0,..,TN,S0,...,SM>.
+ *
+ * \tparam Head Head of resulting tuple
+ * \tparam Tail Tail of resulting tuple
+ */
+ template<class Head, class Tail>
+ struct JoinTuples
+ {
+ //! Result of the join operation
+ typedef typename ReduceTuple< PushBackTuple, Tail, Head>::type type;
+ };
+
+
+
+ /**
+ * \brief Flatten a tuple of tuples
+ *
+ * This flattens a tuple of tuples tuple<tuple<T0,...,TN>, tuple<S0,...,SM> >
+ * and exports tuple<T0,..,TN,S0,...,SM>.
+ *
+ * \tparam TupleTuple A tuple of tuples
+ */
+ template<class TupleTuple>
+ struct FlattenTuple
+ {
+ //! Result of the flatten operation
+ typedef typename ReduceTuple< JoinTuples, TupleTuple>::type type;
+ };
+
+}
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_TYPETRAITS_HH
+#define DUNE_TYPETRAITS_HH
+
+#if defined HAVE_TYPE_TRAITS
+#include <type_traits>
+#elif defined HAVE_TR1_TYPE_TRAITS
+#include <tr1/type_traits>
+#endif
+
+#include <dune/common/deprecated.hh>
+
+namespace Dune
+{
+
+ /**
+ * @file
+ * @brief Traits for type conversions and type information.
+ * @author Markus Blatt, Christian Engwer
+ */
+ /** @addtogroup Common
+ *
+ * @{
+ */
+
+ /**
+ * @brief Just an empty class
+ */
+ struct Empty {};
+
+ /**
+ * @brief General type traits class to check whether type is reference or
+ * pointer type
+ *
+ * \deprecated This class will be replaced by alternatives found in the C++11 stl.
+ * - Use is_pointer<T>::value instead of TypeTraits<T>::isPointer
+ * - Use is_lvalue_reference<T>::value instead of TypeTraits<T>::isReference
+ * - Use remove_pointer<T>::type instead of TypeTraits<T>::PointeeType
+ * - Use remove_reference<T>::type instead of TypeTraits<T>::ReferredType
+ */
+ template <typename T>
+ class TypeTraits
+ {
+ private:
+ template <class U>
+ struct PointerTraits {
+ enum { result = false };
+ typedef Empty PointeeType;
+ };
+
+ template <class U>
+ struct PointerTraits<U*> {
+ enum { result = true };
+ typedef U PointeeType;
+ };
+
+ template <class U> struct ReferenceTraits
+ {
+ enum { result = false };
+ typedef U ReferredType;
+ };
+
+ template <class U> struct ReferenceTraits<U&>
+ {
+ enum { result = true };
+ typedef U ReferredType;
+ };
+
+ public:
+ enum { isPointer = PointerTraits<T>::result };
+ typedef typename PointerTraits<T>::PointeeType PointeeType DUNE_DEPRECATED_MSG("Use remove_pointer instead!");
+
+ enum { isReference = ReferenceTraits<T>::result };
+ typedef typename ReferenceTraits<T>::ReferredType ReferredType DUNE_DEPRECATED_MSG("Use remove_reference instead!");
+ };
+
+ /**
+ * @brief Determines wether a type is const or volatile and provides the
+ * unqualified types.
+ */
+ template<typename T>
+ struct ConstantVolatileTraits
+ {
+ enum {
+ /** @brief True if T has a volatile specifier. */
+ isVolatile=false,
+ /** @brief True if T has a const qualifier. */
+ isConst=false
+ };
+
+ /** @brief The unqualified type. */
+ typedef T UnqualifiedType;
+ /** @brief The const type. */
+ typedef const T ConstType;
+ /** @brief The const volatile type. */
+ typedef const volatile T ConstVolatileType;
+ };
+
+ template<typename T>
+ struct ConstantVolatileTraits<const T>
+ {
+ enum {
+ isVolatile=false, isConst=true
+ };
+ typedef T UnqualifiedType;
+ typedef const UnqualifiedType ConstType;
+ typedef const volatile UnqualifiedType ConstVolatileType;
+ };
+
+
+ template<typename T>
+ struct ConstantVolatileTraits<volatile T>
+ {
+ enum {
+ isVolatile=true, isConst=false
+ };
+ typedef T UnqualifiedType;
+ typedef const UnqualifiedType ConstType;
+ typedef const volatile UnqualifiedType ConstVolatileType;
+ };
+
+ template<typename T>
+ struct ConstantVolatileTraits<const volatile T>
+ {
+ enum {
+ isVolatile=true, isConst=true
+ };
+ typedef T UnqualifiedType;
+ typedef const UnqualifiedType ConstType;
+ typedef const volatile UnqualifiedType ConstVolatileType;
+ };
+
+ /** @brief Tests wether a type is volatile. */
+ template<typename T>
+ struct IsVolatile
+ {
+ enum {
+ /** @brief True if The type is volatile. */
+ value=ConstantVolatileTraits<T>::isVolatile
+ };
+ };
+
+ /** @brief Tests wether a type is constant. */
+ template<typename T>
+ struct IsConst
+ {
+ enum {
+ /** @brief True if The type is constant. */
+ value=ConstantVolatileTraits<T>::isConst
+ };
+ };
+
+ template<typename T, bool isVolatile>
+ struct RemoveConstHelper
+ {
+ typedef typename ConstantVolatileTraits<T>::UnqualifiedType Type;
+ };
+
+ template<typename T>
+ struct RemoveConstHelper<T,true>
+ {
+ typedef volatile typename ConstantVolatileTraits<T>::UnqualifiedType Type;
+ };
+
+#if defined HAVE_TYPE_TRAITS
+ using std::remove_const;
+#elif defined HAVE_TR1_TYPE_TRAITS
+ using std::tr1::remove_const;
+#else
+ /**
+ * @brief Removes a const qualifier while preserving others.
+ */
+ template<typename T>
+ struct remove_const
+ {
+ typedef typename RemoveConstHelper<T, IsVolatile<T>::value>::Type type;
+ };
+#endif
+
+#if defined HAVE_TYPE_TRAITS
+ using std::remove_reference;
+#elif defined HAVE_TR1_TYPE_TRAITS
+ using std::tr1::remove_reference;
+#else
+ //! Remove a reference from a type
+ /**
+ * If the template parameter \c T matches \c T1&, then the member typedef \c
+ * type is \c T1, otherwise it is \c T.
+ */
+ template<typename T> struct remove_reference {
+ //! T with references removed
+ typedef T type;
+ };
+# ifndef DOXYGEN
+ template<typename T> struct remove_reference<T&> {
+ typedef T type;
+ };
+# endif // ! defined(DOXYGEN)
+#endif
+
+ /**
+ * @brief Checks wether a type is convertible to another.
+ *
+ * @tparam From type you want to convert
+ * @tparam To type you want to obtain
+ *
+ * Inspired by
+ * <A HREF="http://www.kotiposti.net/epulkkin/instructive/base-class-determination.html"> this website</A>
+ */
+ template<class From, class To>
+ class Conversion
+ {
+ typedef char Small;
+ struct Big {char dummy[2];};
+ static Small test(To);
+ static Big test(...);
+ static typename remove_reference< From >::type &makeFrom ();
+
+ public:
+ enum {
+ /** @brief True if the conversion exists. */
+ exists = sizeof(test(makeFrom())) == sizeof(Small),
+ /** @brief Whether the conversion exists in both ways. */
+ isTwoWay = exists && Conversion<To,From>::exists,
+ /** @brief True if To and From are the same type. */
+ sameType = false
+ };
+ Conversion(){}
+
+ };
+
+ template <class From>
+ class Conversion<From, void>
+ {
+ public:
+ enum {
+ exists = false,
+ isTwoWay = false,
+ sameType = false
+ };
+ };
+
+ template <class To>
+ class Conversion<void, To>
+ {
+ public:
+ enum {
+ exists = false,
+ isTwoWay = false,
+ sameType = false
+ };
+ };
+
+ template<>
+ class Conversion< int, double >
+ {
+ public:
+ enum {
+ exists = true,
+ isTwoWay = false,
+ sameType = false
+ };
+ };
+
+ template<class T>
+ class Conversion<T,T>{
+ public:
+ enum { exists=true, isTwoWay=true, sameType=true};
+ };
+
+ /**
+ * @brief Checks wether a type is derived from another.
+ *
+ * @tparam Base the potential base class you want to test for
+ * @tparam Derived type you want to test
+ *
+ * Similar idea to
+ * <A HREF="http://www.kotiposti.net/epulkkin/instructive/base-class-determination.html"> this website</A>
+ */
+ template <class Base, class Derived>
+ class IsBaseOf
+ {
+ typedef typename ConstantVolatileTraits< typename remove_reference< Base >::type >::UnqualifiedType RawBase;
+ typedef typename ConstantVolatileTraits< typename remove_reference< Derived >::type >::UnqualifiedType RawDerived;
+ typedef char Small;
+ struct Big {char dummy[2];};
+ static Small test(RawBase*);
+ static Big test(...);
+ static RawDerived* &makePtr ();
+ public:
+ enum {
+ /** @brief True if Base is a base class of Derived. */
+ value = sizeof(test(makePtr())) == sizeof(Small)
+ };
+ IsBaseOf(){}
+
+ };
+
+ /**
+ * @brief Checks wether two types are interoperable.
+ *
+ * Two types are interoperable if conversions in either directions
+ * exists.
+ */
+ template<class T1, class T2>
+ struct IsInteroperable
+ {
+ enum {
+ /**
+ * @brief True if either a conversion from T1 to T2 or vice versa
+ * exists.
+ */
+ value = Conversion<T1,T2>::exists || Conversion<T2,T1>::exists
+ };
+ };
+
+#ifdef HAVE_TYPE_TRAITS
+ using std::enable_if;
+#else
+ /**
+ * @brief Enable typedef if condition is met.
+ *
+ * Replacement implementation for compilers without this in the stl.
+ * Depending on the value of b the type T is provided as typedef type.
+ */
+ template<bool b, typename T=void>
+ struct enable_if
+ {
+ typedef T type;
+ };
+
+ template<typename T>
+ struct enable_if<false,T>
+ {};
+#endif
+
+
+ /**
+ * @brief Enable typedef if two types are interoperable.
+ *
+ * (also see IsInteroperable)
+ */
+ template<class T1, class T2, class Type>
+ struct EnableIfInterOperable
+ : public enable_if<IsInteroperable<T1,T2>::value, Type>
+ {};
+
+#if defined HAVE_TYPE_TRAITS
+ using std::is_same;
+#elif defined HAVE_TR1_TYPE_TRAITS
+ using std::tr1::is_same;
+#else
+ /**
+ * @brief Compile time test for testing whether
+ * two types are the same.
+ */
+ template<typename T1, typename T2>
+ struct is_same
+ {
+ //! Whether T1 is the same type as T2.
+ enum {
+ /* @brief Whether T1 is the same type as T2. */
+ value=false
+ };
+ };
+
+
+ template<typename T>
+ struct is_same<T,T>
+ {
+ enum { value=true};
+ };
+#endif
+
+ /**
+ * @brief Select a type based on a condition.
+ *
+ * If template parameter first is true T1 is selected
+ * otherwise T2 will be selected.
+ * The selected type is accessible through the typedef
+ * Type.
+ *
+ * \deprecated Will be removed after dune-common-2.3, use 'conditional' instead.
+ */
+ template<bool first, class T1, class T2>
+ struct SelectType
+ {
+ /**
+ * @brief The selected type.
+ *
+ * if first is true this will be type T1 and
+ * otherwise T2
+ */
+ typedef T1 Type DUNE_DEPRECATED_MSG("Use Dune::conditional::type instead");
+ } DUNE_DEPRECATED;
+
+ template<class T1, class T2>
+ struct SelectType<false,T1,T2>
+ {
+ typedef T2 Type DUNE_DEPRECATED_MSG("Use Dune::conditional::type instead");
+ };
+
+#if DOXYGEN || !HAVE_STD_CONDITIONAL
+
+ /**
+ * @brief Select a type based on a condition.
+ *
+ * If template parameter first is true T1 is selected
+ * otherwise T2 will be selected.
+ * The selected type is accessible through the typedef
+ * type.
+ *
+ * \note If available, this uses C++11 std::conditional, otherwise it provides
+ * a reimplementation.
+ */
+ template<bool first, class T1, class T2>
+ struct conditional
+ {
+ /**
+ * @brief The selected type
+ *
+ * if first is true this will be type T1 and
+ * T2 otherwise
+ */
+ typedef T1 type;
+ };
+
+ template<class T1, class T2>
+ struct conditional<false,T1,T2>
+ {
+ typedef T2 type;
+ };
+
+#else // DOXYGEN || !HAVE_STD_CONDITIONAL
+
+ // pull in default implementation
+ using std::conditional;
+
+#endif // DOXYGEN || !HAVE_STD_CONDITIONAL
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // integral_constant (C++0x 20.7.3 "Helper classes")
+ //
+#if HAVE_INTEGRAL_CONSTANT
+ using std::integral_constant;
+ using std::true_type;
+ using std::false_type;
+#else // #if HAVE_INTEGRAL_CONSTANT
+ //! Generate a type for a given integral constant
+ /**
+ * \tparam T Type of the constant.
+ * \tparam v Value of the constant.
+ */
+ template <class T, T v>
+ struct integral_constant {
+ //! value this type was generated for
+ static const T value = v;
+ //! type of value
+ typedef T value_type;
+ //! type of this class itself
+ typedef integral_constant<T,v> type;
+ //! conversion to value_type/T
+ operator value_type() { return value; }
+ };
+
+ //! type for true
+ typedef integral_constant<bool, true> true_type;
+ //! type for false
+ typedef integral_constant<bool, false> false_type;
+#endif // #else // #if HAVE_INTEGRAL_CONSTANT
+
+ template<typename>
+ struct __is_pointer_helper
+ : public false_type { };
+
+ template<typename T>
+ struct __is_pointer_helper<T*>
+ : public true_type { };
+
+ /// is_pointer
+ template<typename T>
+ struct is_pointer
+ : public integral_constant<bool, (__is_pointer_helper<T>::value)>
+ { };
+
+ // Helper class for is_lvalue_reference
+ template<typename>
+ struct __is_lvalue_reference_helper
+ : public false_type { };
+
+ template<typename T>
+ struct __is_lvalue_reference_helper<T&>
+ : public true_type { };
+
+ /** \brief Determine whether a type is a lvalue reference type */
+ template<typename T>
+ struct is_lvalue_reference
+ : public integral_constant<bool, (__is_lvalue_reference_helper<T>::value)>
+ { };
+
+ template<typename _Tp>
+ struct __remove_pointer_helper
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ struct __remove_pointer_helper<_Tp*>
+ { typedef _Tp type; };
+
+ /** \brief Return the type a pointer type points to
+ *
+ * \note When the argument T is not a pointer, TypeTraits::PointeeType returns Dune::Empty,
+ * while Dune::remove_pointer (as std::remove_pointer), returns T itself.
+ */
+ template<typename _Tp>
+ struct remove_pointer
+ : public __remove_pointer_helper<typename remove_const<_Tp>::type >
+ { };
+
+ /** @} */
+}
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_COMMON_UNUSED_HH
+#define DUNE_COMMON_UNUSED_HH
+
+/** \file
+ * \brief Definition of the DUNE_UNUSED macro for the case that config.h
+ * is not available
+ */
+
+#ifndef HAS_ATTRIBUTE_UNUSED
+#define DUNE_UNUSED
+#else
+#define DUNE_UNUSED __attribute__((unused))
+#endif
+
+/// A macro to mark intentional unused function parameters with.
+#define DUNE_UNUSED_PARAMETER(parm) static_cast<void>(parm)
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_VERSION_HH
+#define DUNE_VERSION_HH
+
+/** \file
+ * \brief Various macros to work with %Dune module version numbers
+ */
+
+/** \brief Constructs the preprocessor name used in config.h to hold version numbers
+ *
+ * For the DUNE core modules you need to use the following module names:
+ * - DUNE_COMMON for dune-common
+ * - DUNE_GRID for dune-grid
+ * - DUNE_GEOMETRY for dune-geometry
+ * - DUNE_ISTL for dune-istl
+ * - DUNE_LOCALFUNCTIONS for dune-localfunctions
+ *
+ * For external DUNE modules, you should capitalize the name and
+ * replace '-' by underscores. For example for the module foo-bar you
+ * need to use FOO_BAR as module name in the context of this macro.
+ *
+ * \param module The name of the Dune module
+ * \param type The version number type, one of MAJOR, MINOR, or REVISION
+ */
+#define DUNE_VERSION_JOIN(module,type) module ## _VERSION_ ## type
+
+/**
+ * \brief True if 'module' has the version major.minor
+ *
+ * For the DUNE core modules you need to use the following module names:
+ * - DUNE_COMMON for dune-common
+ * - DUNE_GRID for dune-grid
+ * - DUNE_GEOMETRY for dune-geometry
+ * - DUNE_ISTL for dune-istl
+ * - DUNE_LOCALFUNCTIONS for dune-localfunctions
+ *
+ * For external DUNE modules, you should capitalize the name and
+ * replace '-' by underscores. For example for the module foo-bar you
+ * need to use FOO_BAR as module name in the context of this macro.
+ */
+#define DUNE_VERSION_EQUAL(module,major,minor) \
+ ((DUNE_VERSION_JOIN(module,MAJOR) == major) && \
+ (DUNE_VERSION_JOIN(module,MINOR) == minor))
+
+/**
+ * \brief True if 'module' has the version major.minor.revision
+ *
+ * For the DUNE core modules you need to use the following module names:
+ * - DUNE_COMMON for dune-common
+ * - DUNE_GRID for dune-grid
+ * - DUNE_GEOMETRY for dune-geometry
+ * - DUNE_ISTL for dune-istl
+ * - DUNE_LOCALFUNCTIONS for dune-localfunctions
+ *
+ * For external DUNE modules, you should capitalize the name and
+ * replace '-' by underscores. For example for the module foo-bar you
+ * need to use FOO_BAR as module name in the context of this macro.
+ */
+#define DUNE_VERSION_EQUAL_REV(module,major,minor,revision) \
+ ( DUNE_VERSION_EQUAL(module,major,minor) && \
+ (DUNE_VERSION_JOIN(module,REVISION) == revision))
+
+/**
+ * \brief True if 'module' has the version major.minor or newer
+ *
+ * For the DUNE core modules you need to use the following module names:
+ * - DUNE_COMMON for dune-common
+ * - DUNE_GRID for dune-grid
+ * - DUNE_GEOMETRY for dune-geometry
+ * - DUNE_ISTL for dune-istl
+ * - DUNE_LOCALFUNCTIONS for dune-localfunctions
+ *
+ * For external DUNE modules, you should capitalize the name and
+ * replace '-' by underscores. For example for the module foo-bar you
+ * need to use FOO_BAR as module name in the context of this macro.
+ */
+#define DUNE_VERSION_NEWER(module,major,minor) \
+ ((DUNE_VERSION_JOIN(module,MAJOR) > major) \
+ || ((DUNE_VERSION_JOIN(module,MAJOR) == major) && (DUNE_VERSION_JOIN(module,MINOR) >= minor)))
+
+/**
+ * \brief True if 'module' has the version major.minor.revision or newer
+ *
+ * For the DUNE core modules you need to use the following module names:
+ * - DUNE_COMMON for dune-common
+ * - DUNE_GRID for dune-grid
+ * - DUNE_GEOMETRY for dune-geometry
+ * - DUNE_ISTL for dune-istl
+ * - DUNE_LOCALFUNCTIONS for dune-localfunctions
+ *
+ * For external DUNE modules, you should capitalize the name and
+ * replace '-' by underscores. For example for the module foo-bar you
+ * need to use FOO_BAR as module name in the context of this macro.
+ */
+#define DUNE_VERSION_NEWER_REV(module,major,minor,revision) \
+ ((DUNE_VERSION_JOIN(module,MAJOR) > major) \
+ || ((DUNE_VERSION_JOIN(module,MAJOR) == major) && (DUNE_VERSION_JOIN(module,MINOR) > minor)) \
+ || ((DUNE_VERSION_JOIN(module,MAJOR) == major) && (DUNE_VERSION_JOIN(module,MINOR) == minor) \
+ && (DUNE_VERSION_JOIN(module,REVISION) >= revision)))
+
+/**
+ * \brief Compute a unique uint id from the major, minor, and revision numbers
+ *
+ * For the DUNE core modules you need to use the following module names:
+ * - DUNE_COMMON for dune-common
+ * - DUNE_GRID for dune-grid
+ * - DUNE_GEOMETRY for dune-geometry
+ * - DUNE_ISTL for dune-istl
+ * - DUNE_LOCALFUNCTIONS for dune-localfunctions
+ *
+ * For external DUNE modules, you should capitalize the name and
+ * replace '-' by underscores. For example for the module foo-bar you
+ * need to use FOO_BAR as module name in the context of this macro.
+ */
+#define DUNE_VERSION_ID(major,minor,revision) \
+ ((unsigned int)((major << 24) + (minor << 16) + revision))
+
+/**
+ * \brief Compute a unique uint id for the given module
+ *
+ * For the DUNE core modules you need to use the following module names:
+ * - DUNE_COMMON for dune-common
+ * - DUNE_GRID for dune-grid
+ * - DUNE_GEOMETRY for dune-geometry
+ * - DUNE_ISTL for dune-istl
+ * - DUNE_LOCALFUNCTIONS for dune-localfunctions
+ *
+ * For external DUNE modules, you should capitalize the name and
+ * replace '-' by underscores. For example for the module foo-bar you
+ * need to use FOO_BAR as module name in the context of this macro.
+ */
+#define DUNE_MODULE_VERSION_ID(module) \
+ DUNE_VERSION_ID( DUNE_VERSION_JOIN(module,MAJOR), DUNE_VERSION_JOIN(module,MINOR), DUNE_VERSION_JOIN(module,REVISION) )
+
+#endif
--- /dev/null
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_COMMON_VISIBILITY_HH
+#define DUNE_COMMON_VISIBILITY_HH
+
+/** \file
+ * \brief Definition of macros controlling symbol visibility at the ABI level.
+ */
+
+#ifdef DOXYGEN
+
+//! Export a symbol as part of the public ABI.
+/**
+ * Mark a class, function or static variable as visible outside the current DSO.
+ * For now, this is mostly important for templated global variables and functions
+ * that contain static variables.
+ */
+#define DUNE_EXPORT implementation_defined
+
+//! Mark a symbol as being for internal use within the current DSO only.
+/**
+ * Mark a class, function or static variable as inaccessible from outside the current DSO.
+ * Doing so will decrease the size of the symbol table, but you have to be sure that the
+ * symbol will never have to be accessed from another library or the main executable!
+ */
+#define DUNE_PRIVATE implementation_defined
+
+#else // DOXYGEN
+
+#if __GNUC__ >= 4
+// GCC and Clang both define __GNUC__ to 4 and they both support the visibility
+// attribute
+#define DUNE_EXPORT __attribute__((visibility("default")))
+#define DUNE_PRIVATE __attribute__((visibility("hidden")))
+#else
+// We don't know about the active compiler, so just turn the visibility macros to no-ops.
+#define DUNE_EXPORT
+#define DUNE_PRIVATE
+#endif
+
+#endif // DOXYGEN
+
+#endif // DUNE_COMMON_VISIBILITY
--- /dev/null
+libdunecommon.la
+
+Makefile.in
+Makefile
+
+.deps
+.libs
--- /dev/null
+install(FILES dunemodules.lib dunecommonam2cmake.lib
+ DESTINATION ${CMAKE_INSTALL_BINDIR}/../lib)
--- /dev/null
+# $Id: $
+dunemodulelibdir=$(libdir)
+
+EXTRA_DIST = CMakeLists.txt dunemodules.lib dunecommonam2cmake.lib
+dunemodulelib_DATA = dunemodules.lib dunecommonam2cmake.lib
+
+#the dune-common library
+lib_LTLIBRARIES = libdunecommon.la
+
+# this is just a renaming of libcommon to prevent name clashes
+libdunecommon_la_SOURCES =
+# This forces automake to use the C++ linker
+# (see the automake manual, section "Libtool Convenience Libraries")
+nodist_EXTRA_libdunecommon_la_SOURCES = dummy.cc
+sourcescheck_DUMMY = dummy.cc
+libdunecommon_la_LIBADD = ../dune/common/libcommon.la
+
+include $(top_srcdir)/am/global-rules
--- /dev/null
+# -*-sh-*-
+
+##########################################
+###
+### Function for converting configure options
+### to CMake options for dune-common
+###
+##########################################
+space=" "
+tab=" "
+BLANK="$space$tab"
+
+dune_common_options_am2cmake()
+{
+ # CMake Packages are case sensitive
+ # This is a list of packages whose names converted
+ # to lower case are used for configures
+ # --with-<package> or without-<package> options
+ #
+ CMAKE_PACKAGES="Boost Inkscape GMP LAPACK"
+
+ default_am2cmake_options $CMAKE_PACKAGES
+
+ # Check for --enable-parallel and otherwise deactivate MPI
+ echo $PARAMS | grep \\-\\-enable-parallel > /dev/null
+ if test "$?" -ne 0 ; then
+ CMAKE_PARAMS="$CMAKE_PARAMS -DCMAKE_DISABLE_FIND_PACKAGE_MPI=TRUE"
+ else
+ CMAKE_PARAMS="$CMAKE_PARAMS -DUSE_MPI=ON"
+ fi
+ # Check for --disable-gxx0xcheck
+ echo $PARAMS | grep \\-\\-disable-gxx0xcheck > /dev/null
+ if test "$?" -eq 0 ; then
+ CMAKE_PARAMS="$CMAKE_PARAMS -DDISABLE_GXX0XCHECK:BOOL=TRUE"
+ fi
+
+ # Check for --disable-gxx0xcheck
+ echo $PARAMS | grep \\-\\-disable-tr1-headers > /dev/null
+ if test "$?" -eq 0 ; then
+ CMAKE_PARAMS="$CMAKE_PARAMS -DDISABLE_TR1_HEADERS:BOOL=TRUE"
+ fi
+
+ # Check for --with-minimal-debug-level
+ local arg=`echo "$PARAMS"| grep \\\\--with-minimal-debug-level= | sed "s/.*--with-minimal-debug-level=\([^$BLANK]*\).*/\1/"`
+ if test "x$arg" != "x"; then
+ CMAKE_PARAMS="$CMAKE_PARAMS -DMINIMAL_DEBUG_LEVEL:String=$arg"
+ fi
+
+ #Check for --prefix
+ local arg=`echo "$PARAMS"| grep \\\\--prefix= | sed "s/.*--prefix=\([^$BLANK]*\).*/\1/"`
+ if test "x$arg" != "x"; then
+ CMAKE_PARAMS="$CMAKE_PARAMS -DCMAKE_INSTALL_PREFIX=$arg"
+ fi
+}
--- /dev/null
+# -*-sh-*-
+
+###############################################
+###
+### Configuration
+###
+
+# name of the "control" files
+CONTROL="dune.module"
+
+###############################################
+###
+### check for environment variables
+###
+
+if test -z $GREP; then
+ GREP=grep
+fi
+if test -z "$SED"; then
+ SED=sed
+fi
+# SunOS [e]grep does not seem to comprehend character classes. Set up
+# some variables to spell them out
+UPPER=ABCDEFGHIJKLMNOPQRSTUVWXYZ
+LOWER=abcdefghijklmnopqrstuvwxyz
+ALPHA="$UPPER$LOWER"
+DIGIT=0123456789
+ALNUM="$ALPHA$DIGIT"
+
+space=" "
+formfeed="\f"
+newline="
+"
+cr="
+"
+tab=" "
+vtab="\v"
+# $SPACE will unfortunately not work since grep will not accept an
+# embedded newline. Instead one can often get away with using $BLANK
+SPACE="$space$formfeed$newline$cr$tab$vtab"
+BLANK="$space$tab"
+NOBLANK="^$space$tab"
+
+#
+# read paramters from a $CONTROL file
+#
+# paramters:
+# $1 file to read
+#
+PARSER_TRIM="awk '{gsub(/^[ \\t]+|[ \\t]+$/,\"\");printf(\"%s\", \$0);}'"
+parse_control() {
+ # check file existence
+ if test ! -f "$1" -o "$(basename "$1")" != "$CONTROL"; then
+ echo "ERROR: '$1' is no $CONTROL file" >&2
+ exit 1
+ fi
+ # reset information handling
+ module=""
+ module_inst="no"
+ # read parameters from control file
+ local name="$($GREP Module: "$1" | cut -d ':' -f2 | eval $PARSER_TRIM)"
+ if test "x$name" = "x"; then
+ echo "ERROR: $CONTROL files $1 does not contain a Module entry" >&2
+ exit 1
+ fi
+ # create and check variable name from module name
+ export module=$(fix_variable_name $name)
+ if ! check_modname "$module"; then
+ echo "ERROR: $CONTROL files $1 contains an invalid Module entry" >&2
+ exit 1
+ fi
+ # read dune.module file
+ local deps="$($GREP "^[BLANK]*Depends:" "$1" | cut -d ':' -f2 | eval $PARSER_TRIM)"
+ local sugs="$($GREP "^[BLANK]*Suggests:" "$1" | cut -d ':' -f2 | eval $PARSER_TRIM)"
+ local vers="$($GREP "^[BLANK]*Version:" "$1" | cut -d ':' -f2 | eval $PARSER_TRIM)"
+ local main="$($GREP "^[BLANK]*Maintainer:" "$1" | cut -d ':' -f2 | eval $PARSER_TRIM)"
+ # check whether the module is installed.
+ # - installed modules can be found via pkg-config
+ # - pkg-config --var=prefix should be the same as $path
+ #
+ # the path contains a different sub structure
+ # for installed and source modules
+ # - installed module: ${path}/lib/dunecontrol/${name}/dune.module
+ # and there is a file ${path}/lib/pkgconfig/${name}.pc
+ # - source module: ${path}/dune.module
+ # and there is a file ${path}/${name}.pc.in
+ local path="$(canonicalpath "$1")"
+ if pkg-config $name; then
+ local prefix="$(pkg-config --variable=prefix $name)"
+ local pkgpath=$(canonicalname "$prefix/lib/dunecontrol/$name")
+ if test x"$pkgpath" = x"$path"; then
+ path="$prefix"
+ module_inst="yes"
+ fi
+ fi
+ # avoid multiple definition of the same module
+ if eval test "x\$HAVE_$module" != "x"; then
+ # make sure we don't stumble over the same module twice
+ if eval test "\$PATH_$module" = "$path"; then
+ return
+ fi
+ local old_mod_inst
+ eval old_mod_inst=\$INST_$module
+ case "$old_mod_inst$module_inst" in
+ # multiple local modules are an error
+ # multiple installed modules are an error
+ nono|yesyes)
+ echo "ERROR: multiple definition of module $name" >&2
+ echo "previous defined in:" >&2
+ if eval test x\$INST_$module = "xyes"; then
+ echo " $(eval echo \$PATH_$module)/lib/dunecontrol/$name/$CONTROL" >&2
+ else
+ echo " $(eval echo \$PATH_$module)/$CONTROL" >&2
+ fi
+ echo "redefined in:" >&2
+ if test "$module_inst" = "yes"; then
+ echo " $path/lib/dunecontrol/$name/$CONTROL" >&2
+ else
+ echo " $path/$CONTROL" >&2
+ fi
+ exit 1
+ ;;
+ # installed modules are superseded by locally built modules
+ noyes)
+ return
+ ;;
+ # local modules supersede installed modules
+ yesno)
+ superseded_modules="$superseded_modules $path"
+ true # do nothing, ignore the previously found module
+ ;;
+ esac
+ fi
+ # set status variables
+ export HAVE_$module=yes
+ export PATH_$module="$path"
+ export VERS_$module="$vers"
+ export NAME_$module="$name"
+ export MAIN_$module="$main"
+ export DEPS_$module="$deps"
+ export INST_$module="$module_inst"
+ for name in $deps; do
+ mod=$(fix_variable_name $name)
+ export NAME_$mod="$name"
+ done
+ export SUGS_$module="$sugs"
+ for name in $sugs; do
+ mod=$(fix_variable_name $name)
+ export NAME_$mod="$name"
+ done
+ # update list of modules
+ if test "$module_inst" = "yes"; then
+ export INSTMODULES="$INSTMODULES$module "
+ else
+ export LOCALMODULES="$LOCALMODULES$module "
+ fi
+}
+
+# Uses the current compiler to extract information about the
+# multiarch triplets and sets the export variable MULTIARCH_LIBDIR
+# according to it.
+# If not compiler is specified then cc or gcc is used.
+extract_multiarch_pkg_config_path(){
+ local my_cxx_compiler
+ if test "x$MULTIARCH_LIBDIR" != "x"; then
+ return
+ fi
+ set +e #error in the multiarch detection should not be fatal.
+ $(which cc &>/dev/null)
+ if test $? -eq "0"; then
+ my_cxx_compiler=cc
+ else
+ my_cxx_compiler=gcc
+ fi
+ multiarch=$($my_cxx_compiler --print-multiarch 2>/dev/null)
+ if test $? -gt 0; then
+ for i in "target=" "Target:"; do
+ multiarch=$($my_cxx_compiler -v 2>&1| $GREP "$i" | sed "s/.*$i[$BLANK]*\([a-z0-9_-]*\)/\1/" | $SED "s/-[a-z]*-linux-gnu/-linux-gnu/")
+ if test -n "$multiarch"; then break; fi
+ done
+ fi
+ set -e # set to old value.
+ export MULTIARCH_LIBDIR="lib/$multiarch"
+
+ # create PKG_CONFIG_PATH for installed dune modules
+ for i in $MULTIARCH_LIBDIR lib64 lib32 lib; do
+ if test -d "$PREFIX_DIR/$i/pkgconfig"; then
+ export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$PREFIX_DIR/$i/pkgconfig"
+ fi
+ done
+}
+
+
+#
+# try to setup the control path
+#
+setup_control_path() {
+ if test -z "$DUNE_CONTROL_PATH"; then
+ DUNE_CONTROL_PATH=.
+ # try pkg-config locations
+ if ! pkg-config dune-common; then
+ # try usual locations of installed modules
+ for i in /usr/local/lib/dunecontrol/ /usr/lib/dunecontrol/; do
+ if test -d $i; then
+ DUNE_CONTROL_PATH=$DUNE_CONTROL_PATH:"$i"
+ fi
+ done
+ for i in `echo $PKG_CONFIG_PATH | tr ':' ' '`; do
+ if test -d "$i/../dunecontrol"; then
+ DUNE_CONTROL_PATH=$DUNE_CONTROL_PATH:"$i/../dunecontrol"
+ fi
+ done
+ else
+ DUNE_CONTROL_PATH=$DUNE_CONTROL_PATH:$(pkg-config dune-common --variable=prefix)/lib/dunecontrol
+ fi
+ fi
+ # try to read DUNE_CONTROL_PATH from OPTS file
+ if test -n "$DUNE_OPTS_FILE"; then
+ DUNE_CONTROL_PATH="$(. $DUNE_OPTS_FILE; eval echo $DUNE_CONTROL_PATH)"
+ fi
+ # canonicalize path
+ local TMP=""
+ # foreach dir in $@
+ while read dir; do
+ TMP=$TMP:"$(canonicalname "$dir")"
+ done <<EOF
+ $(echo $DUNE_CONTROL_PATH | sed -e 's/:\+/:/g' | tr ':' '\n')
+EOF
+ # sort+uniq path
+ DUNE_CONTROL_PATH="$(echo $TMP | tr ':' '\n' | sort -u | tr '\n' ':' | sed -e 's/^://' -e 's/:$//')"
+ # safe result
+ export DUNE_CONTROL_PATH
+}
+
+#
+# search for modules in each directory in DUNE_CONTROL_PATH
+#
+find_modules_in_path() {
+ setup_control_path
+ if test -z "$FOUND_MODULES"; then
+ # foreach dir in $@
+ while read dir; do
+ if test -d "$dir"; then
+ while read m; do
+ test -n "$m" && parse_control "$m"
+ done <<EOFM
+ $(find -H "$dir" -name $CONTROL | $GREP -v 'dune-[-_a-zA-Z]/dune-[-a-zA-Z_]*-[0-9]\{1,\}.[0-9]\{1,\}/')
+EOFM
+ else
+ parse_control "$dir"
+ fi
+ done <<EOF
+ $(echo $DUNE_CONTROL_PATH | sed -e 's/:\+/:/g' | tr ':' '\n')
+EOF
+ export MODULES="$LOCALMODULES$INSTMODULES"
+ export FOUND_MODULES="$MODULES"
+ else
+ export MODULES="$FOUND_MODULES"
+ fi
+}
+
+#
+# sort $MODULES according to the dependencies
+#
+sort_modules() {
+ # reset lists
+ export SORTEDMODULES=""
+ export REVERSEMODULES=""
+ export SORTEDMODULES_SUB=""
+ # handle each modules passed as parameter
+ for m in "$@"; do
+ # did we find a module file for this module?
+ if eval test x\$HAVE_$m != x; then
+ _sort_module $m MAIN
+ else
+ echo "ERROR: could not find module $(eval echo \$NAME_$m)" >&2
+ exit 1
+ fi
+ done
+ # save result
+ export MODULES="$SORTEDMODULES"
+ # setup list of SUGS/DEPS and the INFO list
+ export SORTEDMODULES_INFO=""
+ export SORTEDMODULES_DEPS=""
+ export SORTEDMODULES_MAIN=""
+ export SORTEDMODULES_SUGS=""
+ local mode
+ for m in $MODULES; do
+ eval mode=\$MODE_$m
+ SORTEDMODULES_INFO="$SORTEDMODULES_INFO $m[$mode]"
+ eval SORTEDMODULES_$mode=\"\$SORTEDMODULES_$mode $m\"
+ done
+ export SORTEDMODULES_INFO
+ export SORTEDMODULES_DEPS
+ export SORTEDMODULES_SUGS
+ export SORTEDMODULES_MAIN
+ # clean up temporary variables
+ for m in $MODULES; do
+ export MODE_$m=""
+ export SORT_DONE_$m=""
+ export SORT_DEPS_DONE_$m=""
+ export SORT_SUGS_DONE_$m=""
+ done
+}
+
+_check_deps()
+{
+ local module="$1"
+ local mode="$2"
+ local depmode="$3"
+ local report="ERROR"
+ local requires="requires"
+ local required="required"
+ local dependency="dependency"
+ if test "x$mode" = "xSUGS"; then
+ report="WARNING"
+ requires="suggests"
+ required="suggested"
+ dependency="suggestion"
+ fi
+ eval deps=\$${mode}_$module
+ #initially remove leading space
+ deps=`echo ${deps//^[, ]}`
+ while test -n "$deps"; do
+ #the end of the name is marked either by space, opening parenthesis,
+ #or comma
+ name="${deps%%[ (,]*}"
+ #remove the name and adjacent whitespace
+ deps=`echo "$deps" | sed 's/^[^ (,]* *//'`
+ #check whether there is a dependency version
+ case "$deps" in
+ '('*) deps="${deps#(}"
+ depver="${deps%%)*}"
+ deps="${deps#*)}"
+ ;;
+ *) depver=
+ ;;
+ esac
+ #remove any leading whitespace or commas for the next iteration
+ deps=`echo ${deps//^[, ]}`
+ dep=$(fix_variable_name $name)
+ if ! check_modname $dep; then
+ echo "ERROR: invalid module name $name ($dependency of $module)" >&2
+ exit 1
+ fi
+ if eval test x\$HAVE_$dep != "x"; then
+ eval ver=\$VERS_$dep
+ if test "$SKIPVERSIONCHECK" != "yes" && ! check_version "$ver" "$depver"; then
+ echo "$report: version mismatch." >&2
+ echo " $modname $requires $name $depver," >&2
+ echo " but only $name = $ver is available." >&2
+ if test "x$mode" = "xDEPS"; then
+ exit 1
+ else
+ echo "Skipping $name!" >&2
+ continue
+ fi
+ fi
+ _sort_module $dep $depmode
+ else
+ # perhaps this module is installed,
+ # then it should be handled via pkg-config
+ if ! pkg-config $name; then
+ echo "$report: could not find module $name," >&2
+ echo " module is also unknown to pkg-config." >&2
+ echo " Maybe you need to adjust PKG_CONFIG_PATH!" >&2
+ echo " $name is $required by $modname" >&2
+ if test "x$mode" = "xDEPS"; then
+ exit 1
+ else
+ echo "Skipping $name!" >&2
+ continue
+ fi
+ else
+ eval ver=$(pkg-config $name --modversion)
+ if test "$SKIPVERSIONCHECK" != "yes" && ! check_version "$ver" "$depver"; then
+ echo "$report: version mismatch." >&2
+ echo " $modname $requires $name $depver," >&2
+ echo " but only $name = $ver is installed." >&2
+ if test "x$mode" = "xDEPS"; then
+ exit 1
+ else
+ echo "Skipping $name!" >&2
+ continue
+ fi
+ fi
+ # update module list
+ parse_control $(pkg-config $name --variable=prefix)/lib/dunecontrol/$name/dune.module
+ _sort_module $dep $depmode
+ fi
+ fi
+ done
+}
+
+#
+# recursive part of sort_modules
+# evaluate dependencies of one module
+#
+# paramters:
+# $1 name of the modules
+# $2 parser mode:
+# DEPS: search for dependencies
+# SUSG: search for suggestions (DEPS of SUGS are handled as SUGS)
+# MAIN: primary invocation of a DEPS search,
+# MAIN modules are not added to the list of DEPS/SUGS
+#
+_sort_module() {
+ local module="$1"
+ local mode="$2"
+ test -n "$mode"
+ local modname=""
+ eval modname=\$NAME_$module
+ local deps=""
+ local name=""
+ local dep=""
+ local ver=""
+ local depver=""
+ shift 1
+ if ! check_modname $module; then
+ echo "ERROR: invalid module name $module" >&2
+ exit 1
+ fi
+ depmode=$(test $mode = SUGS && echo SUGS || echo DEPS)
+ if eval test "x\$SORT_${depmode}_DONE_$module" != "xyes"; then
+ # stop any recursion
+ export SORT_${depmode}_DONE_$module=yes
+ # resolve dependencies
+ _check_deps $module DEPS $depmode # it might happen that the DEPS are actually SUGS
+ # resolve suggestions
+ _check_deps $module SUGS SUGS
+ # remember mode of the module
+ if eval test "x\$MODE_$module" = xSUGS -o "x\$MODE_$module" = x; then
+ export MODE_$module=$mode
+ fi
+ # topological list of the module and its dependencies/suggestions
+ if eval test "x\$SORT_DONE_$module" != "xyes"; then
+ export SORT_DONE_$module=yes
+ export SORTEDMODULES="$SORTEDMODULES $module"
+ export REVERSEMODULES="$module $REVERSEMODULES"
+ fi
+ fi
+}
+
+#
+# load the $CONTROL file, skip all control variables
+# and run a command
+#
+# parameters:
+# $1 command to execute
+# $2 full path of the $CONTROL file
+#
+eval_control() {
+ local command="$1"
+ local file="$2"
+ shift 2
+ if test -f "$file"; then
+ # open subshell
+ (
+ set -e
+ # load functions defined in $file
+ # if $command is not defined in $file,
+ # then the default implementation will be executed
+ eval "$($GREP -v "^[-$ALNUM]\{1,\}:" "$file")"
+ # execute $command
+ $command
+ ) || false
+ else
+ echo "ERROR: could not find $file" >&2
+ exit 1
+ fi
+}
+
+#
+# fix a value such that it is suitable for a variable name
+#
+# parameters:
+# $1 value
+#
+fix_variable_name() {
+ echo ${@//[[:punct:]]/_}
+}
+
+#
+# fix a value such that it is suitable for a variable name and assign it
+#
+# parameters:
+# $1 name of variable
+# $2 value
+#
+fix_and_assign() {
+ local name="$1"
+ if ! check_modname $name; then
+ echo "ERROR: error in assignment. $name is not a valid variabel name." >&2
+ fi
+ shift 1
+ export $name=$(fix_variable_name $@)
+}
+
+#
+# make sure the module name fits the naming convention
+# (we try to assign the name and report upon failure)
+#
+# parameters:
+# $1 module name
+#
+check_modname() {
+ # magic pattern match, see http://www.linuxmisc.com/9-unix-questions/67d307ca51f16ed4.htm
+ [ -n "${1##*[!A-Za-z0-9_]*}" ] && [ -n "${1##[!A-Za-z_]*}" ]
+}
+
+#
+# compare a sub part of the version string
+#
+# parameters:
+# $1 version
+# $2 part
+#
+# parts:
+# 1: major
+# 2: minor
+# 3: revision
+#
+get_sub_version() {
+ #it would be nice to give the part to awk via a "-v FIELD=$2"
+ #command line argument. Unfortunatly, SunOS does not support this.
+ #Worse, we cannot use awks int() function here, since under SunOS it
+ #will always return 0 for string input.
+ echo $1 | cut -d. -f"$2" | sed 's/[^0-9].*$//;s/^$/0/'
+}
+
+#
+# compare two versions
+#
+# parameters:
+# $1 version1
+# $2 version1
+#
+# return:
+# 0: equal
+# 1: v1 > v2
+# 2: v1 < v2
+#
+compare_versions() {
+ local v1="$1"
+ local v2="$2"
+
+ for i in 1 2 3; do
+ compare_sub_version $v1 $v2 $i || return 0
+ done
+
+ echo "eq"
+}
+
+compare_sub_version() {
+ # compare sub version number
+ local sub1=`get_sub_version $1 $3`
+ local sub2=`get_sub_version $2 $3`
+
+ if test $sub1 -gt $sub2; then
+ echo "gt"
+ return 1
+ fi
+ if test $sub1 -lt $sub2; then
+ echo "lt"
+ return 1
+ fi
+
+ return 0
+}
+
+check_version() {
+ if test -z "$2"; then # if no constraint is given, check_version is true
+ return 0
+ fi
+ local v=$1
+ local PATTERN="^ *\([<>=]*\) *\([0-9.]*\)\(.*\)$"
+ if test x != `echo "$2" | sed -e "s/$PATTERN/x/"`; then
+ echo "ERROR: invalid version constraint $2" >&2
+ exit 1
+ fi
+ local op=`echo "$2" | sed -e "s/$PATTERN/\1/"`
+ local v2=`echo "$2" | sed -e "s/$PATTERN/\2/"`
+ local rest=`echo "$2" | sed -e "s/$PATTERN/\3/" -e 's/ //g'`
+ local result=1
+
+ local rel=`compare_versions $v $v2`
+
+ case $rel$op in
+ "eq<="|"eq="|"eq>="|\
+ "gt>="|"gt>"|\
+ "lt<="|"lt<")
+ result=0
+ ;;
+ esac
+ if test -z "$rest"; then
+ return $result
+ fi
+ PATTERN="\([|&]\{2\}\)\(.*\)$"
+ if test xx != x`echo "$rest" | sed -e "s/$PATTERN/x/"`; then
+ echo "ERROR: invalid version constraint '$rest'" >&2
+ exit 1
+ fi
+ op=`echo "$rest" | sed -e "s/$PATTERN/\1/"`
+ v2=`echo "$rest" | sed -e "s/$PATTERN/\2/"`
+ if eval "test $result -eq 0" $op "check_version \"$v\" \"$v2\""; then
+ return 0
+ fi
+ return 1
+}
+
+#
+# Function that the translates options for configure
+# The arguments are the case sensitive cmake package names.
+# It is assumed that their lowercase version is used
+# for the autotools. This function either deactivates
+# a package using CMAKE_DISABLE_FIND_PACKAGE_<package>=TRUE
+# or passes th provided path using
+# the <CMAKE_PACKAGE_ALL_UPPERCASE>_ROOT variable
+default_am2cmake_options(){
+ while test "$#" -gt 0; do
+ local package=$1
+ local lowercase=`tr 'A-Z' 'a-z' <<< $1`
+ local uppercase=`tr 'a-z' 'A-Z' <<< $1`
+ shift
+ if eval test \$"$lowercase"_processed ; then
+ continue
+ fi
+ export "$lowercase"_processed=1
+ # check for --without-$lowercase
+ echo $PARAMS | grep \\-\\-without-$lowercase > /dev/null
+ if test "$?" -eq 0 ; then
+ CMAKE_PARAMS="$CMAKE_PARAMS -DCMAKE_DISABLE_FIND_PACKAGE_$package=TRUE"
+ continue
+ fi
+ # process --with-$lowercase=<arg>
+ local arg=`echo $PARAMS| sed "s/.*--with-$lowercase=\([$NOBLANK]*\).*/\1/"`
+ local arg=`eval echo $arg` # expand tilde to prevent problems
+ if test "x$arg" = "xno"; then
+ CMAKE_PARAMS="$CMAKE_PARAMS -DCMAKE_DISABLE_FIND_PACKAGE_$package=TRUE"
+ continue
+ fi
+ if test -d "$arg"; then
+ CMAKE_PARAMS="$CMAKE_PARAMS -D$uppercase""_ROOT=$arg"
+ fi
+ done
+ export CMAKE_PARAMS
+}
+
+
+# Default translation routine for libraries.
+# Arguments are the CMake package names.
+# Searches for --with-<package>lib=<library>
+# in the configure options and translates them
+# to -D<PACKAGE>_LIBRARY=<library>
+default_am2cmake_libraries(){
+ while test "$#" -gt 0; do
+ lib=$1
+ local lowercase=`tr 'A-Z' 'a-z' <<< $1`
+ local uppercase=`tr 'a-z' 'A-Z' <<< $1`
+ shift
+ if eval test \$"$lowercase"-lib_processed; then
+ continue
+ fi
+ export "$lowercase"-lib_processed=1
+ term="s/.*--with-""$lowercase""-lib=\([$NOBLANK]*\).*/\1/"
+ arg=`echo "$PARAMS" | grep \\-\\-with-$lowercase | sed "$term"`
+ if test "x$arg" != "x"; then
+ CMAKE_PARAMS="$CMAKE_PARAMS -D$uppercase""_LIBRARY=$arg"
+ fi
+ done
+}
+
+module_translate_options_am2cmake()
+{
+ local module=$1 # the module name
+ local path=$2 # where the sh libs reside
+
+ # Check whether the module provides a lib named
+ # <module-without-dashes>autotools2cmake.lib
+ local module_undashed=`echo $module | sed "s/[-_]//g"`
+ local libfile="$path/$module_undashed""am2cmake.lib"
+ if test -e "$libfile"; then
+ . $libfile
+ local module_underline=`echo $module | sed "s/-/_/g"`
+ eval "$module_underline"_options_am2cmake
+ else
+ echo "$libfile for converting options does not exist"
+ fi
+}
--- /dev/null
+Makefile
+Makefile.in
+semantic.cache
\ No newline at end of file
--- /dev/null
+install(PROGRAMS
+ acx_blas.m4
+ acx_lapack.m4
+ acx_mpi.m4
+ acx_pthread.m4
+ ax_boost_base.m4
+ ax_check_gl.m4
+ ax_lang_compiler_ms.m4
+ boost_fusion.m4
+ cxx0x_compiler.m4
+ cxx0x_rvaluereference.m4
+ cxx0x_nullptr.m4
+ cxx0x_static_assert.m4
+ cxx0x_variadic.m4
+ cxx0x_variadic_constructor_sfinae.m4
+ cxx11_constexpr.m4
+ cxx11_initializer_list.m4
+ cxx11_conditional.m4
+ dune.m4
+ dune_all.m4
+ dune_autobuild.m4
+ dune_boost_base.m4
+ dune_check_lib.m4
+ dune_common.m4
+ dune_compiler.m4
+ dune_cxa_demangle.m4
+ dune_fortran.m4
+ dune_deprecated.m4
+ dune_deprecated_cppflags.m4
+ dune_docu.m4
+ dune_linkcxx.m4
+ dune_mpi.m4
+ dune_streams.m4
+ dune_tr1_headers.m4
+ dune_unused.m4
+ fortran_overwrite.m4
+ gmp.m4
+ hdf5.m4
+ immdx_lib_metis.m4
+ inkscape.m4
+ libtoolcompat.m4
+ make_shared.m4
+ mprotect.m4
+ mpi-config.m4
+ opengl.m4
+ parmetis.m4
+ shared_ptr.m4
+ umfpack.m4
+ xdr.m4
+ DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/dune/aclocal
+)
--- /dev/null
+# -*- tab-width: 8 -*-
+# vi: set ts=8:
+# $Id$
+
+ALLM4S = \
+ acx_blas.m4 \
+ acx_lapack.m4 \
+ acx_mpi.m4 \
+ acx_pthread.m4 \
+ ax_boost_base.m4 \
+ ax_check_gl.m4 \
+ ax_lang_compiler_ms.m4 \
+ boost_fusion.m4 \
+ cxx0x_compiler.m4 \
+ cxx0x_rvaluereference.m4 \
+ cxx0x_nullptr.m4 \
+ cxx0x_static_assert.m4 \
+ cxx0x_variadic.m4 \
+ cxx0x_variadic_constructor_sfinae.m4 \
+ cxx11_initializer_list.m4 \
+ cxx11_conditional.m4 \
+ cxx11_constexpr.m4 \
+ dune.m4 \
+ dune_all.m4 \
+ dune_autobuild.m4 \
+ dune_boost_base.m4 \
+ dune_check_lib.m4 \
+ dune_common.m4 \
+ dune_compiler.m4 \
+ dune_cxa_demangle.m4 \
+ dune_fortran.m4 \
+ dune_deprecated.m4 \
+ dune_deprecated_cppflags.m4 \
+ dune_docu.m4 \
+ dune_linkcxx.m4 \
+ dune_mpi.m4 \
+ dune_streams.m4 \
+ dune_tr1_headers.m4 \
+ dune_unused.m4 \
+ fortran_overwrite.m4 \
+ gmp.m4 \
+ hdf5.m4 \
+ immdx_lib_metis.m4 \
+ inkscape.m4 \
+ libtoolcompat.m4 \
+ make_shared.m4 \
+ mpi-config.m4 \
+ mprotect.m4 \
+ opengl.m4 \
+ parmetis.m4 \
+ shared_ptr.m4 \
+ umfpack.m4 \
+ xdr.m4
+
+aclocaldir = $(datadir)/dune/aclocal
+aclocal_DATA = $(ALLM4S)
+
+EXTRA_DIST = CMakeLists.txt $(ALLM4S)
+
+include $(top_srcdir)/am/global-rules
--- /dev/null
+dnl @synopsis ACX_BLAS([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+dnl
+dnl This macro looks for a library that implements the BLAS
+dnl linear-algebra interface (see http://www.netlib.org/blas/). On
+dnl success, it sets the BLAS_LIBS output variable to hold the
+dnl requisite library linkages.
+dnl
+dnl To link with BLAS, you should link with:
+dnl
+dnl $BLAS_LIBS $LIBS $FLIBS
+dnl
+dnl in that order. FLIBS is the output variable of the
+dnl AC_F77_LIBRARY_LDFLAGS macro (called if necessary by ACX_BLAS), and
+dnl is sometimes necessary in order to link with F77 libraries. Users
+dnl will also need to use AC_F77_DUMMY_MAIN (see the autoconf manual),
+dnl for the same reason.
+dnl
+dnl Many libraries are searched for, from ATLAS to CXML to ESSL. The
+dnl user may also use --with-blas=<lib> in order to use some specific
+dnl BLAS library <lib>. In order to link successfully, however, be
+dnl aware that you will probably need to use the same Fortran compiler
+dnl (which can be set via the F77 env. var.) as was used to compile the
+dnl BLAS library.
+dnl
+dnl ACTION-IF-FOUND is a list of shell commands to run if a BLAS
+dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to
+dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the
+dnl default action will define HAVE_BLAS.
+dnl
+dnl This macro requires autoconf 2.50 or later.
+dnl
+dnl @category InstalledPackages
+dnl @author Steven G. Johnson <stevenj@alum.mit.edu>
+dnl @version 2001-12-13
+dnl @license GPLWithACException
+
+AC_DEFUN([ACX_BLAS], [
+AC_PREREQ(2.50)
+AC_REQUIRE([AC_F77_LIBRARY_LDFLAGS])
+acx_blas_ok=no
+
+AC_ARG_WITH(blas,
+ [AC_HELP_STRING([--with-blas=<lib>], [use BLAS library <lib>])])
+case $with_blas in
+ yes | "") ;;
+ no) acx_blas_ok=disable ;;
+ -* | */* | *.a | *.so | *.so.* | *.o) BLAS_LIBS="$with_blas" ;;
+ *) BLAS_LIBS="-l$with_blas" ;;
+esac
+
+# Get fortran linker names of BLAS functions to check for.
+AC_F77_FUNC(sgemm)
+AC_F77_FUNC(dgemm)
+
+acx_blas_save_LIBS="$LIBS"
+LIBS="$LIBS $FLIBS"
+
+# First, check BLAS_LIBS environment variable
+if test $acx_blas_ok = no; then
+if test "x$BLAS_LIBS" != x; then
+ save_LIBS="$LIBS"; LIBS="$BLAS_LIBS $LIBS"
+ AC_MSG_CHECKING([for $sgemm in $BLAS_LIBS])
+ AC_LINK_IFELSE(
+ [AC_LANG_CALL([], $sgemm)],
+ [acx_blas_ok=yes],
+ [BLAS_LIBS=""])
+ AC_MSG_RESULT($acx_blas_ok)
+ LIBS="$save_LIBS"
+fi
+fi
+
+# BLAS linked to by default? (happens on some supercomputers)
+if test $acx_blas_ok = no; then
+ save_LIBS="$LIBS"; LIBS="$LIBS"
+ AC_CHECK_FUNC($sgemm, [acx_blas_ok=yes])
+ LIBS="$save_LIBS"
+fi
+
+# BLAS in ATLAS library? (http://math-atlas.sourceforge.net/)
+if test $acx_blas_ok = no; then
+ AC_CHECK_LIB(atlas, ATL_xerbla,
+ [AC_CHECK_LIB(f77blas, $sgemm,
+ [AC_CHECK_LIB(cblas, cblas_dgemm,
+ [acx_blas_ok=yes
+ BLAS_LIBS="-lcblas -lf77blas -latlas"],
+ [], [-lf77blas -latlas])],
+ [], [-latlas])])
+fi
+
+# BLAS in PhiPACK libraries? (requires generic BLAS lib, too)
+if test $acx_blas_ok = no; then
+ AC_CHECK_LIB(blas, $sgemm,
+ [AC_CHECK_LIB(dgemm, $dgemm,
+ [AC_CHECK_LIB(sgemm, $sgemm,
+ [acx_blas_ok=yes; BLAS_LIBS="-lsgemm -ldgemm -lblas"],
+ [], [-lblas])],
+ [], [-lblas])])
+fi
+
+# BLAS in Alpha CXML library?
+if test $acx_blas_ok = no; then
+ AC_CHECK_LIB(cxml, $sgemm, [acx_blas_ok=yes;BLAS_LIBS="-lcxml"])
+fi
+
+# BLAS in Alpha DXML library? (now called CXML, see above)
+if test $acx_blas_ok = no; then
+ AC_CHECK_LIB(dxml, $sgemm, [acx_blas_ok=yes;BLAS_LIBS="-ldxml"])
+fi
+
+# BLAS in Sun Performance library?
+if test $acx_blas_ok = no; then
+ if test "x$GCC" != xyes; then # only works with Sun CC
+ AC_CHECK_LIB(sunmath, acosp,
+ [AC_CHECK_LIB(sunperf, $sgemm,
+ [BLAS_LIBS="-xlic_lib=sunperf -lsunmath"
+ acx_blas_ok=yes],[],[-lsunmath])])
+ fi
+fi
+
+# BLAS in SCSL library? (SGI/Cray Scientific Library)
+if test $acx_blas_ok = no; then
+ AC_CHECK_LIB(scs, $sgemm, [acx_blas_ok=yes; BLAS_LIBS="-lscs"])
+fi
+
+# BLAS in SGIMATH library?
+if test $acx_blas_ok = no; then
+ AC_CHECK_LIB(complib.sgimath, $sgemm,
+ [acx_blas_ok=yes; BLAS_LIBS="-lcomplib.sgimath"])
+fi
+
+# BLAS in IBM ESSL library? (requires generic BLAS lib, too)
+if test $acx_blas_ok = no; then
+ AC_CHECK_LIB(blas, $sgemm,
+ [AC_CHECK_LIB(essl, $sgemm,
+ [acx_blas_ok=yes; BLAS_LIBS="-lessl -lblas"],
+ [], [-lblas $FLIBS])])
+fi
+
+# Generic BLAS library?
+if test $acx_blas_ok = no; then
+ AC_CHECK_LIB(blas, $sgemm, [acx_blas_ok=yes; BLAS_LIBS="-lblas"])
+fi
+
+AC_SUBST(BLAS_LIBS)
+
+LIBS="$acx_blas_save_LIBS"
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_blas_ok" = xyes; then
+ ifelse([$1],,AC_DEFINE(HAVE_BLAS,1,[Define if you have a BLAS library.]),[$1])
+ :
+else
+ acx_blas_ok=no
+ $2
+fi
+])dnl ACX_BLAS
--- /dev/null
+dnl @synopsis ACX_LAPACK([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+dnl
+dnl This macro looks for a library that implements the LAPACK
+dnl linear-algebra interface (see http://www.netlib.org/lapack/). On
+dnl success, it sets the LAPACK_LIBS output variable to hold the
+dnl requisite library linkages.
+dnl
+dnl To link with LAPACK, you should link with:
+dnl
+dnl $LAPACK_LIBS $BLAS_LIBS $LIBS $FLIBS
+dnl
+dnl in that order. BLAS_LIBS is the output variable of the ACX_BLAS
+dnl macro, called automatically. FLIBS is the output variable of the
+dnl AC_F77_LIBRARY_LDFLAGS macro (called if necessary by ACX_BLAS), and
+dnl is sometimes necessary in order to link with F77 libraries. Users
+dnl will also need to use AC_F77_DUMMY_MAIN (see the autoconf manual),
+dnl for the same reason.
+dnl
+dnl The user may also use --with-lapack=<lib> in order to use some
+dnl specific LAPACK library <lib>. In order to link successfully,
+dnl however, be aware that you will probably need to use the same
+dnl Fortran compiler (which can be set via the F77 env. var.) as was
+dnl used to compile the LAPACK and BLAS libraries.
+dnl
+dnl ACTION-IF-FOUND is a list of shell commands to run if a LAPACK
+dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to
+dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the
+dnl default action will define HAVE_LAPACK.
+dnl
+dnl @category InstalledPackages
+dnl @author Steven G. Johnson <stevenj@alum.mit.edu>
+dnl @version 2002-03-12
+dnl @license GPLWithACException
+
+AC_DEFUN([ACX_LAPACK], [
+AC_REQUIRE([ACX_BLAS])
+acx_lapack_ok=no
+
+AC_ARG_WITH(lapack,
+ [AC_HELP_STRING([--with-lapack=<lib>], [use LAPACK library <lib>])])
+case $with_lapack in
+ yes | "") ;;
+ no) acx_lapack_ok=disable ;;
+ -* | */* | *.a | *.so | *.so.* | *.o) LAPACK_LIBS="$with_lapack" ;;
+ *) LAPACK_LIBS="-l$with_lapack" ;;
+esac
+
+# Get fortran linker name of LAPACK function to check for.
+AC_F77_FUNC(cheev)
+
+# We cannot use LAPACK if BLAS is not found
+if test "x$acx_blas_ok" != xyes; then
+ acx_lapack_ok=noblas
+fi
+
+# First, check LAPACK_LIBS environment variable
+if test "x$LAPACK_LIBS" != x; then
+ save_LIBS="$LIBS"; LIBS="$LAPACK_LIBS $BLAS_LIBS $LIBS $FLIBS"
+ AC_MSG_CHECKING([for $cheev in $LAPACK_LIBS])
+ AC_LINK_IFELSE(
+ [AC_LANG_CALL([], $cheev)],
+ [acx_lapack_ok=yes],
+ [LAPACK_LIBS=""])
+ AC_MSG_RESULT($acx_lapack_ok)
+ LIBS="$save_LIBS"
+ if test acx_lapack_ok = no; then
+ LAPACK_LIBS=""
+ fi
+fi
+
+# LAPACK linked to by default? (is sometimes included in BLAS lib)
+if test $acx_lapack_ok = no; then
+ save_LIBS="$LIBS"; LIBS="$LIBS $BLAS_LIBS $FLIBS"
+ AC_CHECK_FUNC($cheev, [acx_lapack_ok=yes])
+ LIBS="$save_LIBS"
+fi
+
+# Generic LAPACK library?
+for lapack in lapack lapack_rs6k; do
+ if test $acx_lapack_ok = no; then
+ save_LIBS="$LIBS"; LIBS="$BLAS_LIBS $LIBS"
+ AC_CHECK_LIB($lapack, $cheev,
+ [acx_lapack_ok=yes; LAPACK_LIBS="-l$lapack"], [], [$FLIBS])
+ LIBS="$save_LIBS"
+ fi
+done
+
+AC_SUBST(LAPACK_LIBS)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_lapack_ok" = xyes; then
+ ifelse([$1],,AC_DEFINE(HAVE_LAPACK,1,[Define if you have LAPACK library.]),[$1])
+ :
+else
+ acx_lapack_ok=no
+ $2
+fi
+])dnl ACX_LAPACK
--- /dev/null
+dnl @synopsis ACX_MPI([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+dnl
+dnl This macro tries to find out how to compile programs that use MPI
+dnl (Message Passing Interface), a standard API for parallel process
+dnl communication (see http://www-unix.mcs.anl.gov/mpi/)
+dnl
+dnl On success, it sets the MPICC, MPICXX, or MPIF77 output variable to
+dnl the name of the MPI compiler, depending upon the current language.
+dnl (This may just be $CC/$CXX/$F77, but is more often something like
+dnl mpicc/mpiCC/mpif77.) It also sets MPILIBS to any libraries that are
+dnl needed for linking MPI (e.g. -lmpi, if a special
+dnl MPICC/MPICXX/MPIF77 was not found).
+dnl
+dnl If you want to compile everything with MPI, you should set:
+dnl
+dnl CC="$MPICC" #OR# CXX="$MPICXX" #OR# F77="$MPIF77"
+dnl LIBS="$MPILIBS $LIBS"
+dnl
+dnl The user can force a particular library/compiler by setting the
+dnl MPICC/MPICXX/MPIF77 and/or MPILIBS environment variables.
+dnl
+dnl ACTION-IF-FOUND is a list of shell commands to run if an MPI
+dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to
+dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the
+dnl default action will define HAVE_MPI.
+dnl
+dnl @category InstalledPackages
+dnl @author Steven G. Johnson <stevenj@alum.mit.edu>
+dnl @version 2004-11-05
+dnl @license GPLWithACException
+
+AC_DEFUN([ACX_MPI], [
+AC_PREREQ(2.50) dnl for AC_LANG_CASE
+
+AC_LANG_CASE([C], [
+ AC_REQUIRE([AC_PROG_CC])
+ AC_ARG_VAR(MPICC,[MPI C compiler command])
+ AC_CHECK_PROGS(MPICC, mpicc hcc mpcc mpcc_r mpxlc cmpicc, $CC)
+ acx_mpi_save_CC="$CC"
+ LAMMPICC="$CC"
+ CC="$MPICC"
+ AC_SUBST(MPICC)
+],
+[C++], [
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_ARG_VAR(MPICXX,[MPI C++ compiler command])
+ AC_CHECK_PROGS(MPICXX, mpic++ mpicxx mpiCC mpCC hcp mpxlC mpxlC_r cmpic++, $CXX)
+ acx_mpi_save_CXX="$CXX"
+ LAMMPICXX="$CXX"
+ CXX="$MPICXX"
+ AC_SUBST(MPICXX)
+],
+[Fortran 77], [
+ AC_REQUIRE([AC_PROG_F77])
+ AC_ARG_VAR(MPIF77,[MPI Fortran compiler command])
+ AC_CHECK_PROGS(MPIF77, mpif77 hf77 mpxlf mpf77 mpif90 mpf90 mpxlf90 mpxlf95 mpxlf_r cmpifc cmpif90c, $F77)
+ acx_mpi_save_F77="$F77"
+ LAMMPIF77="$F77"
+ F77="$MPIF77"
+ AC_SUBST(MPIF77)
+])
+
+if test x = x"$MPILIBS"; then
+ AC_LANG_CASE([C], [AC_CHECK_FUNC(MPI_Init, [MPILIBS=" "])],
+ [C++], [AC_CHECK_FUNC(MPI_Init, [MPILIBS=" "])],
+ [Fortran 77], [AC_MSG_CHECKING([for MPI_Init])
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([], [[call MPI_Init]])],
+ [MPILIBS=" "
+ AC_MSG_RESULT(yes)],
+ [AC_MSG_RESULT(no)])])
+fi
+if test x = x"$MPILIBS"; then
+ AC_CHECK_LIB(mpi, MPI_Init, [MPILIBS="-lmpi"])
+fi
+if test x = x"$MPILIBS"; then
+ AC_CHECK_LIB(mpich, MPI_Init, [MPILIBS="-lmpich"])
+fi
+
+dnl We have to use AC_COMPILE_IFELSE and not AC_CHECK_HEADER because the
+dnl latter uses $CPP, not $CC (which may be mpicc).
+AC_LANG_CASE([C], [if test x != x"$MPILIBS"; then
+ AC_MSG_CHECKING([for mpi.h])
+ export LAMMPICC="$acx_mpi_save_CC"
+ AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([[
+ #include <mpi.h>
+ ]], [])],
+ AC_MSG_RESULT(yes),
+ [MPILIBS=""
+ AC_MSG_RESULT(no)])
+ unset LAMMPICC
+fi],
+[C++], [if test x != x"$MPILIBS"; then
+ AC_MSG_CHECKING([for mpi.h])
+ export LAMMPICXX="$acx_mpi_save_CXX"
+ AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([[
+ #include <mpi.h>
+ ]], [])],
+ AC_MSG_RESULT(yes),
+ [MPILIBS=""
+ AC_MSG_RESULT(no)])
+ unset LAMMPICXX
+fi])
+
+AC_LANG_CASE([C], [CC="$acx_mpi_save_CC"],
+ [C++], [CXX="$acx_mpi_save_CXX"],
+ [Fortran 77], [F77="$acx_mpi_save_F77"])
+
+AC_SUBST(MPILIBS)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x = x"$MPILIBS"; then
+ $2
+ :
+else
+ ifelse([$1],,[AC_DEFINE(HAVE_MPI,1,[Define if you have the MPI library.])],[$1])
+ :
+fi
+])dnl ACX_MPI
--- /dev/null
+dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+dnl
+dnl This macro figures out how to build C programs using POSIX threads.
+dnl It sets the PTHREAD_LIBS output variable to the threads library and
+dnl linker flags, and the PTHREAD_CFLAGS output variable to any special
+dnl C compiler flags that are needed. (The user can also force certain
+dnl compiler flags/libs to be tested by setting these environment
+dnl variables.)
+dnl
+dnl Also sets PTHREAD_CC to any special C compiler that is needed for
+dnl multi-threaded programs (defaults to the value of CC otherwise).
+dnl (This is necessary on AIX to use the special cc_r compiler alias.)
+dnl
+dnl NOTE: You are assumed to not only compile your program with these
+dnl flags, but also link it with them as well. e.g. you should link
+dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS
+dnl $LIBS
+dnl
+dnl If you are only building threads programs, you may wish to use
+dnl these variables in your default LIBS, CFLAGS, and CC:
+dnl
+dnl LIBS="$PTHREAD_LIBS $LIBS"
+dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+dnl CC="$PTHREAD_CC"
+dnl
+dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute
+dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to
+dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+dnl
+dnl ACTION-IF-FOUND is a list of shell commands to run if a threads
+dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to
+dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the
+dnl default action will define HAVE_PTHREAD.
+dnl
+dnl Please let the authors know if this macro fails on any platform, or
+dnl if you have any other suggestions or comments. This macro was based
+dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with
+dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros
+dnl posted by Alejandro Forero Cuervo to the autoconf macro repository.
+dnl We are also grateful for the helpful feedback of numerous users.
+dnl
+dnl @category InstalledPackages
+dnl @author Steven G. Johnson <stevenj@alum.mit.edu>
+dnl @version 2005-01-14
+dnl @license GPLWithACException
+
+AC_DEFUN([ACX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_SAVE
+AC_LANG_C
+acx_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+ AC_LINK_IFELSE(
+ [AC_LANG_CALL([], [pthread_join])],
+ [acx_pthread_ok=yes],
+ [])
+ AC_MSG_RESULT($acx_pthread_ok)
+ if test x"$acx_pthread_ok" = xno; then
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+ fi
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try. Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all, and "pthread-config"
+# which is a program returning the flags for the Pth emulation library.
+
+acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important. Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+# other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+# doesn't hurt to check since this sometimes defines pthreads too;
+# also defines -D_REENTRANT)
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case "${host_cpu}-${host_os}" in
+ *solaris*)
+
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (We need to link with -pthread or
+ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
+ # a function called by this macro, so we could check for that, but
+ # who knows whether they'll stub that too in a future libc.) So,
+ # we'll just look for -pthreads and -lpthread first:
+
+ acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags"
+ ;;
+esac
+
+if test x"$acx_pthread_ok" = xno; then
+for flag in $acx_pthread_flags; do
+
+ case $flag in
+ none)
+ AC_MSG_CHECKING([whether pthreads work without any flags])
+ ;;
+
+ -*)
+ AC_MSG_CHECKING([whether pthreads work with $flag])
+ PTHREAD_CFLAGS="$flag"
+ ;;
+
+ pthread-config)
+ AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no)
+ if test x"$acx_pthread_config" = xno; then continue; fi
+ PTHREAD_CFLAGS="`pthread-config --cflags`"
+ PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+ ;;
+
+ *)
+ AC_MSG_CHECKING([for the pthreads library -l$flag])
+ PTHREAD_LIBS="-l$flag"
+ ;;
+ esac
+
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Check for various functions. We must include pthread.h,
+ # since some functions may be macros. (On the Sequent, we
+ # need a special flag -Kthread to make this header compile.)
+ # We check for pthread_join because it is in -lpthread on IRIX
+ # while pthread_create is in libc. We check for pthread_attr_init
+ # due to DEC craziness with -lpthreads. We check for
+ # pthread_cleanup_push because it is one of the few pthread
+ # functions on Solaris that doesn't have a non-functional libc stub.
+ # We try pthread_create on general principles.
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <pthread.h>]],
+ [[pthread_t th; pthread_join(th, 0);
+ pthread_attr_init(0); pthread_cleanup_push(0, 0);
+ pthread_create(0,0,0,0); pthread_cleanup_pop(0);]])],
+ [acx_pthread_ok=yes],
+ [])
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ AC_MSG_RESULT($acx_pthread_ok)
+ if test "x$acx_pthread_ok" = xyes; then
+ break;
+ fi
+
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$acx_pthread_ok" = xyes; then
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+ AC_MSG_CHECKING([for joinable pthread attribute])
+ attr_name=unknown
+ for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <pthread.h>]],
+ [[int attr=$attr;]])],
+ [attr_name=$attr; break],
+ [])
+ done
+ AC_MSG_RESULT($attr_name)
+ if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
+ AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
+ [Define to necessary symbol if this constant
+ uses a non-standard name on your system.])
+ fi
+
+ AC_MSG_CHECKING([if more special flags are required for pthreads])
+ flag=no
+ case "${host_cpu}-${host_os}" in
+ *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
+ *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+ esac
+ AC_MSG_RESULT(${flag})
+ if test "x$flag" != xno; then
+ PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+ fi
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ # More AIX lossage: must compile with cc_r
+ AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC})
+else
+ PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_pthread_ok" = xyes; then
+ ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+ :
+else
+ acx_pthread_ok=no
+ $2
+fi
+AC_LANG_RESTORE
+])dnl ACX_PTHREAD
--- /dev/null
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_boost_base.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_BOOST_BASE([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# DESCRIPTION
+#
+# Test for the Boost C++ libraries of a particular version (or newer)
+#
+# If no path to the installed boost library is given the macro searchs
+# under /usr, /usr/local, /opt and /opt/local and evaluates the
+# $BOOST_ROOT environment variable. Further documentation is available at
+# <http://randspringer.de/boost/index.html>.
+#
+# This macro calls:
+#
+# AC_SUBST(BOOST_CPPFLAGS) / AC_SUBST(BOOST_LDFLAGS)
+#
+# And sets:
+#
+# HAVE_BOOST
+#
+# LICENSE
+#
+# Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>
+# Copyright (c) 2009 Peter Adolphs
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 21
+
+AC_DEFUN([AX_BOOST_BASE],
+[
+AC_ARG_WITH([boost],
+ [AS_HELP_STRING([--with-boost@<:@=ARG@:>@],
+ [use Boost library from a standard location (ARG=yes),
+ from the specified location (ARG=<path>),
+ or disable it (ARG=no)
+ @<:@ARG=yes@:>@ ])],
+ [
+ if test "$withval" = "no"; then
+ want_boost="no"
+ elif test "$withval" = "yes"; then
+ want_boost="yes"
+ ac_boost_path=""
+ else
+ want_boost="yes"
+ ac_boost_path="$withval"
+ fi
+ ],
+ [want_boost="yes"])
+
+
+AC_ARG_WITH([boost-libdir],
+ AS_HELP_STRING([--with-boost-libdir=LIB_DIR],
+ [Force given directory for boost libraries. Note that this will override library path detection, so use this parameter only if default library detection fails and you know exactly where your boost libraries are located.]),
+ [
+ if test -d "$withval"
+ then
+ ac_boost_lib_path="$withval"
+ else
+ AC_MSG_ERROR(--with-boost-libdir expected directory name)
+ fi
+ ],
+ [ac_boost_lib_path=""]
+)
+
+if test "x$want_boost" = "xyes"; then
+ boost_lib_version_req=ifelse([$1], ,1.20.0,$1)
+ boost_lib_version_req_shorten=`expr $boost_lib_version_req : '\([[0-9]]*\.[[0-9]]*\)'`
+ boost_lib_version_req_major=`expr $boost_lib_version_req : '\([[0-9]]*\)'`
+ boost_lib_version_req_minor=`expr $boost_lib_version_req : '[[0-9]]*\.\([[0-9]]*\)'`
+ boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
+ if test "x$boost_lib_version_req_sub_minor" = "x" ; then
+ boost_lib_version_req_sub_minor="0"
+ fi
+ WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+ $boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor`
+ AC_MSG_CHECKING(for boostlib >= $boost_lib_version_req)
+ succeeded=no
+
+ dnl On 64-bit systems check for system libraries in both lib64 and lib.
+ dnl The former is specified by FHS, but e.g. Debian does not adhere to
+ dnl this (as it rises problems for generic multi-arch support).
+ dnl The last entry in the list is chosen by default when no libraries
+ dnl are found, e.g. when only header-only libraries are installed!
+ libsubdirs="lib"
+ ax_arch=`uname -m`
+ if test $ax_arch = x86_64 -o $ax_arch = ppc64 -o $ax_arch = s390x -o $ax_arch = sparc64; then
+ libsubdirs="lib64 lib lib64"
+ fi
+
+ dnl first we check the system location for boost libraries
+ dnl this location ist chosen if boost libraries are installed with the --layout=system option
+ dnl or if you install boost with RPM
+ if test "$ac_boost_path" != ""; then
+ BOOST_CPPFLAGS="-I$ac_boost_path/include"
+ for ac_boost_path_tmp in $libsubdirs; do
+ if test -d "$ac_boost_path"/"$ac_boost_path_tmp" ; then
+ BOOST_LDFLAGS="-L$ac_boost_path/$ac_boost_path_tmp"
+ break
+ fi
+ done
+ elif test "$cross_compiling" != yes; then
+ for ac_boost_path_tmp in /usr /usr/local /opt /opt/local ; do
+ if test -d "$ac_boost_path_tmp/include/boost" && test -r "$ac_boost_path_tmp/include/boost"; then
+ for libsubdir in $libsubdirs ; do
+ if ls "$ac_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
+ done
+ BOOST_LDFLAGS="-L$ac_boost_path_tmp/$libsubdir"
+ BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include"
+ break;
+ fi
+ done
+ fi
+
+ dnl overwrite ld flags if we have required special directory with
+ dnl --with-boost-libdir parameter
+ if test "$ac_boost_lib_path" != ""; then
+ BOOST_LDFLAGS="-L$ac_boost_lib_path"
+ fi
+
+ ax_boost_base_save_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$ax_boost_base_save_CPPFLAGS $BOOST_CPPFLAGS"
+
+ ax_boost_base_save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$ax_boost_base_save_LDFLAGS $BOOST_LDFLAGS"
+
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_LANG_PUSH(C++)
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ @%:@include <boost/version.hpp>
+ ]], [[
+ #if BOOST_VERSION >= $WANT_BOOST_VERSION
+ // Everything is okay
+ #else
+ # error Boost version is too old
+ #endif
+ ]])],[
+ AC_MSG_RESULT(yes)
+ succeeded=yes
+ found_system=yes
+ ],[
+ ])
+ AC_LANG_POP([C++])
+
+
+
+ dnl if we found no boost with system layout we search for boost libraries
+ dnl built and installed without the --layout=system option or for a staged(not installed) version
+ if test "x$succeeded" != "xyes"; then
+ _version=0
+ if test "$ac_boost_path" != ""; then
+ if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then
+ for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do
+ _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
+ V_CHECK=`expr $_version_tmp \> $_version`
+ if test "$V_CHECK" = "1" ; then
+ _version=$_version_tmp
+ fi
+ VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
+ BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE"
+ done
+ fi
+ else
+ if test "$cross_compiling" != yes; then
+ for ac_boost_path in /usr /usr/local /opt /opt/local ; do
+ if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then
+ for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do
+ _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
+ V_CHECK=`expr $_version_tmp \> $_version`
+ if test "$V_CHECK" = "1" ; then
+ _version=$_version_tmp
+ best_path=$ac_boost_path
+ fi
+ done
+ fi
+ done
+
+ VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
+ BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE"
+ if test "$ac_boost_lib_path" = ""; then
+ for libsubdir in $libsubdirs ; do
+ if ls "$best_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
+ done
+ BOOST_LDFLAGS="-L$best_path/$libsubdir"
+ fi
+ fi
+
+ if test "x$BOOST_ROOT" != "x"; then
+ for libsubdir in $libsubdirs ; do
+ if ls "$BOOST_ROOT/stage/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
+ done
+ if test -d "$BOOST_ROOT" && test -r "$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/$libsubdir" && test -r "$BOOST_ROOT/stage/$libsubdir"; then
+ version_dir=`expr //$BOOST_ROOT : '.*/\(.*\)'`
+ stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'`
+ stage_version_shorten=`expr $stage_version : '\([[0-9]]*\.[[0-9]]*\)'`
+ V_CHECK=`expr $stage_version_shorten \>\= $_version`
+ if test "$V_CHECK" = "1" -a "$ac_boost_lib_path" = "" ; then
+ AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT)
+ BOOST_CPPFLAGS="-I$BOOST_ROOT"
+ BOOST_LDFLAGS="-L$BOOST_ROOT/stage/$libsubdir"
+ fi
+ fi
+ fi
+ fi
+
+ CPPFLAGS="$ax_boost_base_save_CPPFLAGS $BOOST_CPPFLAGS"
+ LDFLAGS="$ax_boost_base_save_LDFLAGS $BOOST_LDFLAGS"
+
+ AC_LANG_PUSH(C++)
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ @%:@include <boost/version.hpp>
+ ]], [[
+ #if BOOST_VERSION >= $WANT_BOOST_VERSION
+ // Everything is okay
+ #else
+ # error Boost version is too old
+ #endif
+ ]])],[
+ AC_MSG_RESULT(yes)
+ succeeded=yes
+ found_system=yes
+ ],[
+ ])
+ AC_LANG_POP([C++])
+ fi
+
+ if test "$succeeded" != "yes" ; then
+ if test "$_version" = "0" ; then
+ AC_MSG_NOTICE([[We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in <boost/version.hpp>. See http://randspringer.de/boost for more documentation.]])
+ else
+ AC_MSG_NOTICE([Your boost libraries seems to old (version $_version).])
+ fi
+ # execute ACTION-IF-NOT-FOUND (if present):
+ ifelse([$3], , :, [$3])
+ else
+ AC_SUBST(BOOST_CPPFLAGS)
+ AC_SUBST(BOOST_LDFLAGS)
+ AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available])
+ # execute ACTION-IF-FOUND (if present):
+ ifelse([$2], , :, [$2])
+ fi
+
+ CPPFLAGS="$ax_boost_base_save_CPPFLAGS"
+ LDFLAGS="$ax_boost_base_save_LDFLAGS"
+fi
+
+])
--- /dev/null
+dnl @synopsis AX_CHECK_GL
+dnl
+dnl Check for an OpenGL implementation. If GL is found, the required
+dnl compiler and linker flags are included in the output variables
+dnl "GL_CFLAGS" and "GL_LIBS", respectively. This macro adds the
+dnl configure option "--with-apple-opengl-framework", which users can
+dnl use to indicate that Apple's OpenGL framework should be used on Mac
+dnl OS X. If Apple's OpenGL framework is used, the symbol
+dnl "HAVE_APPLE_OPENGL_FRAMEWORK" is defined. If no GL implementation
+dnl is found, "no_gl" is set to "yes".
+dnl
+dnl @category InstalledPackages
+dnl @author Braden McDaniel <braden@endoframe.com>
+dnl @version 2004-11-15
+dnl @license AllPermissive
+
+AC_DEFUN([AX_CHECK_GL],
+[AC_REQUIRE([AC_PATH_X])dnl
+AC_REQUIRE([ACX_PTHREAD])dnl
+
+#
+# There isn't a reliable way to know we should use the Apple OpenGL framework
+# without a configure option. A Mac OS X user may have installed an
+# alternative GL implementation (e.g., Mesa), which may or may not depend on X.
+#
+AC_ARG_WITH([apple-opengl-framework],
+ [AC_HELP_STRING([--with-apple-opengl-framework],
+ [use Apple OpenGL framework (Mac OS X only)])])
+if test "X$with_apple_opengl_framework" = "Xyes"; then
+ AC_DEFINE([HAVE_APPLE_OPENGL_FRAMEWORK], [1],
+ [Use the Apple OpenGL framework.])
+ GL_LIBS="-framework OpenGL"
+else
+ AC_LANG_PUSH(C)
+
+ AX_LANG_COMPILER_MS
+ if test X$ax_compiler_ms = Xno; then
+ GL_CFLAGS="${PTHREAD_CFLAGS}"
+ GL_LIBS="${PTHREAD_LIBS} -lm"
+ fi
+
+ #
+ # Use x_includes and x_libraries if they have been set (presumably by
+ # AC_PATH_X).
+ #
+ if test "X$no_x" != "Xyes"; then
+ if test -n "$x_includes"; then
+ GL_CFLAGS="-I${x_includes} ${GL_CFLAGS}"
+ fi
+ if test -n "$x_libraries"; then
+ GL_LIBS="-L${x_libraries} -lX11 ${GL_LIBS}"
+ fi
+ fi
+
+ AC_CHECK_HEADERS([windows.h])
+
+ AC_CACHE_CHECK([for OpenGL library], [ax_cv_check_gl_libgl],
+ [ax_cv_check_gl_libgl="no"
+ ax_save_CPPFLAGS="${CPPFLAGS}"
+ CPPFLAGS="${GL_CFLAGS} ${CPPFLAGS}"
+ ax_save_LIBS="${LIBS}"
+ LIBS=""
+ ax_check_libs="-lopengl32 -lGL"
+ for ax_lib in ${ax_check_libs}; do
+ if test X$ax_compiler_ms = Xyes; then
+ ax_try_lib=`echo $ax_lib | sed -e 's/^-l//' -e 's/$/.lib/'`
+ else
+ ax_try_lib="${ax_lib}"
+ fi
+ LIBS="${ax_try_lib} ${GL_LIBS} ${ax_save_LIBS}"
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([[
+# if HAVE_WINDOWS_H && defined(_WIN32)
+# include <windows.h>
+# endif
+# include <GL/gl.h>]],
+ [[glBegin(0)]])],
+ [ax_cv_check_gl_libgl="${ax_try_lib}"; break])
+ done
+ LIBS=${ax_save_LIBS}
+ CPPFLAGS=${ax_save_CPPFLAGS}])
+
+ if test "X${ax_cv_check_gl_libgl}" = "Xno"; then
+ no_gl="yes"
+ GL_CFLAGS=""
+ GL_LIBS=""
+ else
+ GL_LIBS="${ax_cv_check_gl_libgl} ${GL_LIBS}"
+ fi
+ AC_LANG_POP(C)
+fi
+
+AC_SUBST([GL_CFLAGS])
+AC_SUBST([GL_LIBS])
+])dnl
--- /dev/null
+dnl @synopsis AX_LANG_COMPILER_MS
+dnl
+dnl Check whether the compiler for the current language is Microsoft.
+dnl
+dnl This macro is modeled after _AC_LANG_COMPILER_GNU in the GNU
+dnl Autoconf implementation.
+dnl
+dnl @category InstalledPackages
+dnl @author Braden McDaniel <braden@endoframe.com>
+dnl @version 2004-11-15
+dnl @license AllPermissive
+
+AC_DEFUN([AX_LANG_COMPILER_MS],
+[AC_CACHE_CHECK([whether we are using the Microsoft _AC_LANG compiler],
+ [ax_cv_[]_AC_LANG_ABBREV[]_compiler_ms],
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[#ifndef _MSC_VER
+ choke me
+#endif
+]])],
+ [ax_compiler_ms=yes],
+ [ax_compiler_ms=no])
+ax_cv_[]_AC_LANG_ABBREV[]_compiler_ms=$ax_compiler_ms
+])])
--- /dev/null
+# -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+AC_DEFUN([DUNE_BOOST_FUSION],
+[
+ AC_REQUIRE([AC_PROG_CC])
+ CPPFLAGS_SAVED="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+ export CPPFLAGS
+
+ LDFLAGS_SAVED="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+ export LDFLAGS
+
+ AC_CACHE_CHECK(whether the Boost::FUSION library is available,
+ dune_cv_boost_fusion,
+ [AC_LANG_PUSH([C++])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ @%:@include <boost/fusion/container.hpp>
+ ]],
+ [[
+ boost::fusion::vector<int,char,double> v;
+ return 0;
+ ]])],
+ dune_cv_boost_fusion=yes, dune_cv_boost_fusion=no)
+ AC_LANG_POP([C++])])
+ if test "x$dune_cv_boost_fusion" = "xyes"; then
+ AC_DEFINE(HAVE_BOOST_FUSION,,[define if the Boost::Fusion headers are available])
+ fi
+ CPPFLAGS="$CPPFLAGS_SAVED"
+ LDFLAGS="$LDFLAGS_SAVED"
+])
--- /dev/null
+# whether compiler accepts -std=c++11 or -std=c++0x
+# can be disabled by --disable-gxx0xcheck
+
+AC_DEFUN([GXX0X],[
+ ac_save_CXX="$CXX"
+
+ # try flag -std=c++11
+ AC_CACHE_CHECK([whether $CXX accepts -std=c++11], dune_cv_gplusplus_accepts_cplusplus11, [
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_ARG_ENABLE(gxx0xcheck,
+ AC_HELP_STRING([--disable-gxx0xcheck],
+ [Skip test whether compiler supports flag -std=c++11 and -std=c++0x to enable C++11 features (with this option C++11 features will not be activated)]),
+ [gxx0xcheck=$enableval],
+ [gxx0xcheck=yes])
+ if test "x$GXX" = xyes && test "x$gxx0xcheck" = xyes; then
+ AC_LANG_PUSH([C++])
+ CXX="$CXX -std=c++11"
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #include <iostream>
+ #include <array>
+ ]], [])],
+ dune_cv_gplusplus_accepts_cplusplus11=yes,
+ dune_cv_gplusplus_accepts_cplusplus11=no)
+ AC_LANG_POP([C++])
+ fi
+ ])
+ if test "x$dune_cv_gplusplus_accepts_cplusplus11" == "xyes" ; then
+ CXX="$ac_save_CXX -std=c++11"
+ CXXCPP="$CXXCPP -std=c++11"
+ else
+ CXX="$ac_save_CXX"
+
+ # try flag -std=c++0x instead
+ AC_CACHE_CHECK([whether $CXX accepts -std=c++0x], dune_cv_gplusplus_accepts_cplusplus0x, [
+ AC_REQUIRE([AC_PROG_CXX])
+ if test "x$GXX" = xyes && test "x$gxx0xcheck" = xyes; then
+ AC_LANG_PUSH([C++])
+ CXX="$CXX -std=c++0x"
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #include <iostream>
+ #include <array>
+ ]], [])],
+ dune_cv_gplusplus_accepts_cplusplus0x=yes,
+ dune_cv_gplusplus_accepts_cplusplus0x=no)
+ AC_LANG_POP([C++])
+ fi
+ ])
+ if test "x$dune_cv_gplusplus_accepts_cplusplus0x" == "xyes" ; then
+ CXX="$ac_save_CXX -std=c++0x"
+ CXXCPP="$CXXCPP -std=c++0x"
+ else
+ CXX="$ac_save_CXX"
+ fi
+ fi
+])
--- /dev/null
+AC_DEFUN([NULLPTR_CHECK],[
+ AC_CACHE_CHECK([whether nullptr is supported], dune_cv_nullptr_support, [
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_REQUIRE([GXX0X])
+ AC_LANG_PUSH([C++])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+ [],[[
+ char* ch = nullptr;
+ if(ch!=nullptr) { ; }
+ ]])],
+ dune_cv_nullptr_support=yes,
+ dune_cv_nullptr_support=no)
+ AC_LANG_POP
+ ])
+ if test "x$dune_cv_nullptr_support" = xyes; then
+ AC_DEFINE(HAVE_NULLPTR, 1, [Define to 1 if nullptr is supported])
+ fi
+])
--- /dev/null
+# tests compiler support for C++0x rvalue references
+# the associated macro is called HAVE_RVALUE_REFERENCES
+
+AC_DEFUN([RVALUE_REFERENCES_CHECK],[
+ AC_CACHE_CHECK([whether rvalue references are supported], dune_cv_rvalue_references_support, [
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_REQUIRE([GXX0X])
+ AC_LANG_PUSH([C++])
+ AC_RUN_IFELSE([
+ AC_LANG_PROGRAM([#include<cassert>
+ #include <utility>
+ int foo(int&& x) { return 1; }
+ int foo(const int& x) { return -1; }
+
+ template<typename T>
+ int forward(T&& x)
+ {
+ return foo(std::forward<T>(x));
+ }],
+ [
+ int i = 0;
+ assert( forward(i) + forward(int(2)) == 0);
+ return 0;
+ ])],
+ dune_cv_rvalue_references_support=yes,
+ dune_cv_rvalue_references_support=no)
+ AC_LANG_POP
+ ])
+ if test "x$dune_cv_rvalue_references_support" = xyes; then
+ AC_DEFINE(HAVE_RVALUE_REFERENCES, 1, [Define to 1 if rvalue references are supported])
+ fi
+])
--- /dev/null
+AC_DEFUN([STATIC_ASSERT_CHECK],[
+ AC_CACHE_CHECK([whether static_assert is supported], dune_cv_static_assert_support, [
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_REQUIRE([GXX0X])
+ AC_LANG_PUSH([C++])
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([], [[static_assert(true,"MSG")]])],
+ dune_cv_static_assert_support=yes,
+ dune_cv_static_assert_support=no)
+ AC_LANG_POP
+ ])
+ if test "x$dune_cv_static_assert_support" = xyes; then
+ AC_DEFINE(HAVE_STATIC_ASSERT, 1, [Define to 1 if static_assert is supported])
+ fi
+])
--- /dev/null
+# tests for C++0x variadic template support
+# the associated macro is called HAVE_VARIADIC_TEMPLATES
+
+AC_DEFUN([VARIADIC_TEMPLATES_CHECK],[
+ AC_CACHE_CHECK([whether variadic templates are supported], dune_cv_variadic_templates_support, [
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_REQUIRE([GXX0X])
+ AC_LANG_PUSH([C++])
+ AC_RUN_IFELSE([
+ AC_LANG_PROGRAM([#include<cassert>
+
+ template<typename... T>
+ int addints(T... x);
+
+ int add_ints()
+ {
+ return 0;
+ }
+
+ template<typename T1, typename... T>
+ int add_ints(T1 t1, T... t)
+ {
+ return t1 + add_ints(t...);
+ }],
+ [
+ assert( 5 == add_ints(9,3,-5,-2) );
+ return 0;
+ ])],
+ dune_cv_variadic_templates_support=yes,
+ dune_cv_variadic_templates_support=no)
+ AC_LANG_POP
+ ])
+ if test "x$dune_cv_variadic_templates_support" = xyes; then
+ AC_DEFINE(HAVE_VARIADIC_TEMPLATES, 1, [Define to 1 if variadic templates are supported])
+ fi
+])
--- /dev/null
+# tests whether the compiler supports SFINAE on variadic template constructors
+# within template classes. GCC 4.3 fails this test.
+# the associated macro is called HAVE_VARIADIC_CONSTRUCTOR_SFINAE
+
+AC_DEFUN([VARIADIC_CONSTRUCTOR_SFINAE_CHECK],[
+ AC_CACHE_CHECK([whether SFINAE on variadic template constructors is fully supported],
+ dune_cv_variadic_constructor_sfinae_support, [
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_REQUIRE([GXX0X])
+ AC_LANG_PUSH([C++])
+ AC_RUN_IFELSE([
+ AC_LANG_PROGRAM([
+ #include <functional>
+
+ template<typename... U>
+ struct A
+ {
+
+ template<typename... T,
+ typename = typename std::enable_if<(sizeof...(T) < 2)>::type
+ >
+ A(T... t)
+ : i(1)
+ {}
+
+ template<typename... T,
+ typename = typename std::enable_if<(sizeof...(T) >= 2)>::type,
+ typename = void
+ >
+ A(T... t)
+ : i(-1)
+ {}
+
+ A()
+ : i(1)
+ {}
+
+ int i;
+ };],
+ [
+ return (A<int>().i + A<int>(2).i + A<int>("foo",3.4).i + A<int>(8,'a',A<int>()).i == 0 ? 0 : 1);
+ ])],
+ dune_cv_variadic_constructor_sfinae_support=yes,
+ dune_cv_variadic_constructor_sfinae_support=no)
+ AC_LANG_POP
+ ])
+ AS_IF([test "x$dune_cv_variadic_constructor_sfinae_support" = xyes],[
+ AC_DEFINE(HAVE_VARIADIC_CONSTRUCTOR_SFINAE, 1, [Define to 1 if SFINAE on variadic template constructors is fully supported])
+ ])
+])
--- /dev/null
+# tests for C++11 conditional support
+# the associated macro is called HAVE_STD_CONDITIONAL
+
+AC_DEFUN([CXX11_CONDITIONAL_CHECK],[
+ AC_CACHE_CHECK([for C++11 std::conditional], dune_cv_cxx11_conditional_support, [
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_REQUIRE([GXX0X])
+ AC_LANG_PUSH([C++])
+ AC_RUN_IFELSE([
+ AC_LANG_PROGRAM([
+
+ #include <type_traits>
+
+ ],
+ [
+ return std::conditional<true,std::integral_constant<int,0>,void>::type::value;
+ ])],
+ dune_cv_cxx11_conditional_support=yes,
+ dune_cv_cxx11_conditional_support=no)
+ AC_LANG_POP
+ ])
+ if test "x$dune_cv_cxx11_conditional_support" = xyes; then
+ AC_DEFINE(HAVE_STD_CONDITIONAL, 1, [Define to 1 if C++11 std::conditional is supported])
+ fi
+])
--- /dev/null
+# tests for C++11 constexpr support
+# the associated macro is called HAVE_CONSTEXPR
+
+AC_DEFUN([CXX11_CONSTEXPR_CHECK],[
+ AC_CACHE_CHECK([for C++11 constexpr], dune_cv_cxx11_constexpr_support, [
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_REQUIRE([GXX0X])
+ AC_LANG_PUSH([C++])
+ AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([
+ constexpr int foo () { return 0; }
+
+ template< int v >
+ struct A
+ {
+ static const int value = v;
+ };
+ ],[
+ return A< foo() >::value;
+ ])],
+ dune_cv_cxx11_constexpr_support=yes,
+ dune_cv_cxx11_constexpr_support=no)
+ AC_LANG_POP
+ ])
+ if test "x$dune_cv_cxx11_constexpr_support" = xyes; then
+ AC_DEFINE(HAVE_CONSTEXPR, 1, [Define to 1 if C++11 constexpr is supported])
+ fi
+])
--- /dev/null
+# tests for C++11 initializer list support
+# the associated macro is called HAVE_INITIALIZER_LIST
+
+AC_DEFUN([INITIALIZER_LIST_CHECK],[
+ AC_CACHE_CHECK([whether std::initializer_list is supported], dune_cv_initializer_list_support, [
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_REQUIRE([GXX0X])
+ AC_LANG_PUSH([C++])
+ AC_RUN_IFELSE([
+ AC_LANG_PROGRAM([
+
+ #include <initializer_list>
+ #include <vector>
+
+ struct A
+ {
+
+ A(std::initializer_list<int> il)
+ : vec(il)
+ {}
+
+ std::vector<int> vec;
+ };
+
+ ],
+ [
+ A a{1,3,4,5};
+ return 0;
+ ])],
+ dune_cv_initializer_list_support=yes,
+ dune_cv_initializer_list_support=no)
+ AC_LANG_POP
+ ])
+ if test "x$dune_cv_initializer_list_support" = xyes; then
+ AC_DEFINE(HAVE_INITIALIZER_LIST, 1, [Define to 1 if std::initializer_list is supported])
+ fi
+])
--- /dev/null
+dnl -*- autoconf -*-
+# $Id$
+# checks for dune-headers and everything they need
+
+# TODO
+#
+# - use pkg-config if --enable-localdune is not provided
+
+# #export PKG_CONFIG_LIBDIR=$with_dune/dune
+# #PKG_CHECK_MODULES(DUNE, dune)
+
+# DUNE_VAR_IF (VAR, [TEXT], [IF-EQUAL], [IF-NOT-EQUAL])
+#
+# Compatibility wrapper around AS_VAR_IF. If AS_VAR_IF is available, use it,
+# otherwise emulate it.
+AC_DEFUN([DUNE_VAR_IF],
+[m4_ifdef([AS_VAR_IF],
+ [AS_VAR_IF([$1], [$2], [$3], [$4])],
+ [AS_IF([{ _dune_var_if_tmp="$2"
+ eval "test x\"\$AS_ESCAPE([$1])\" = x\"\$_dune_var_if_tmp\""
+ }], [$3], [$4])])
+])
+
+# DUNE_VAR_COPY (DEST, SRC)
+#
+# Compatibility wrapper around AS_VAR_COPY. If AS_VAR_COPY is available, use
+# it, otherwise emulate it.
+AC_DEFUN([DUNE_VAR_COPY],
+[m4_ifdef([AS_VAR_COPY],
+ [AS_VAR_COPY([$1], [$2])],
+ [eval "$1=\$$2"])
+])
+
+# DUNE_VAR_APPEND (VAR, TEXT)
+#
+# Compatibility wrapper around AS_VAR_APPEND. If AS_VAR_APPEND is available,
+# use it, otherwise emulate it.
+AC_DEFUN([DUNE_VAR_APPEND],
+[m4_ifdef([AS_VAR_APPEND],
+ [AS_VAR_APPEND([$1], [$2])],
+ [DUNE_VAR_COPY([_dune_va_tmp], [$1])
+AS_VAR_SET([$1], ["$_dune_va_tmp"$2])])
+])
+
+# DUNE_ADD_ALL_PKG (TAG, [CPPFLAGS], [LDFLAGS], [LIBS])
+#
+# Add the flags and libs of an external library to the ALL_PKG_* variables,
+# avoiding duplicates.
+#
+# TAG Tag used to avoid duplicate entries in the global variables. This
+# should be the same in all invocations of this macro for the same
+# library, even for different modules.
+#
+# CPPFLAGS The preprocessor flags to add.
+#
+# LDFLAGS The linker flags to add.
+#
+# LIBS The libraries to add.
+#
+# All arguments allow shell substitutions. Each argument should be suitable
+# for use inside shell double quotes. The flags given as argument here should
+# not include the flags of dependend libraries that already call
+# DUNE_ADD_ALL_PKG themselves; e.g. HDF5 should not add the DUNEMPI* flags.
+#
+# configure/shell variables:
+# ALL_PKG_CPPFLAGS
+# ALL_PKG_LDFLAGS
+# ALL_PKG_LIBS
+AC_DEFUN([DUNE_ADD_ALL_PKG],
+[AS_VAR_PUSHDEF([_dune_aap_TAG], [_dune_aap_tag_$1])dnl
+AS_VAR_SET_IF([_dune_aap_TAG], [],
+[DUNE_VAR_APPEND([ALL_PKG_CPPFLAGS], [" $2"])
+DUNE_VAR_APPEND([ALL_PKG_LDFLAGS], [" $3"])
+ALL_PKG_LIBS="$4 $ALL_PKG_LIBS"
+AS_VAR_SET([_dune_aap_TAG], [1])
+])
+AS_VAR_POPDEF([_dune_aap_TAG])dnl
+])
+
+# DUNE_ADD_MODULE_DEPS (MODULE, TAG, [CPPFLAGS], [LDFLAGS], [LIBS])
+#
+# Add the flags and libs of an external library to the modules flags
+# and libs and to the the DUNE_* and ALL_PKG_* families of global flags and
+# libs.
+#
+# MODULE The name to the DUNE module to add the flags for. It should be
+# lowercase with components seperated by dashes (like "dune-common").
+#
+# TAG Tag used to avoid duplicate entries in the global variables. This
+# should be the same in all invocations of this macro for the same
+# library, even for different modules.
+#
+# CPPFLAGS The preprocessor flags to add.
+#
+# LDFLAGS The linker flags to add.
+#
+# LIBS The libraries to add.
+#
+# All arguments allow shell substitutions. Each argument should be suitable
+# for use inside shell double quotes.
+#
+# configure/shell variables (MODULE_upper denotes an uppercase version of
+# MODULE as obtained by AS_TR_CPP):
+# {MODULE_upper}_DEPS_CPPFLAGS
+# {MODULE_upper}_DEPS_LDFLAGS
+# {MODULE_upper}_DEPS_LIBS
+# ALL_PKG_CPPFLAGS
+# ALL_PKG_LDFLAGS
+# ALL_PKG_LIBS
+# DUNE_CPPFLAGS
+# DUNE_LDFLAGS
+# DUNE_LIBS
+AC_DEFUN([DUNE_ADD_MODULE_DEPS],
+[# Add module specific flags and libs
+AS_VAR_PUSHDEF([_dune_amd_CPPFLAGS], [AS_TR_CPP([$1])_DEPS_CPPFLAGS])dnl
+DUNE_VAR_COPY([_dune_amd_tmp], [_dune_amd_CPPFLAGS])
+AS_VAR_SET([_dune_amd_CPPFLAGS], ["$3 "$_dune_amd_tmp])
+AS_VAR_POPDEF([_dune_amd_CPPFLAGS])dnl
+
+AS_VAR_PUSHDEF([_dune_amd_LDFLAGS], [AS_TR_CPP([$1])_DEPS_LDFLAGS])dnl
+DUNE_VAR_COPY([_dune_amd_tmp], [_dune_amd_LDFLAGS])
+AS_VAR_SET([_dune_amd_LDFLAGS], ["$4 "$_dune_amd_tmp])
+AS_VAR_POPDEF([_dune_amd_LDFLAGS])dnl
+
+AS_VAR_PUSHDEF([_dune_amd_LIBS], [AS_TR_CPP([$1])_DEPS_LIBS])dnl
+DUNE_VAR_COPY([_dune_amd_tmp], [_dune_amd_LIBS])
+AS_VAR_SET([_dune_amd_LIBS], ["$5 "$_dune_amd_tmp])
+AS_VAR_POPDEF([_dune_amd_LIBS])dnl
+
+# add flags and libs to the ALL_PKG_* family
+DUNE_ADD_ALL_PKG([$2], [\${_DUNE_MODULE[]_CPPFLAGS}], [\${_DUNE_MODULE[]_LDFLAGS}], [\${_DUNE_MODULE[]_LIBS}])
+
+# add flags and libs to the DUNE_* family
+AS_VAR_PUSHDEF([_dune_amd_TAG], [_dune_amd_tag_$2])dnl
+AS_VAR_SET_IF([_dune_amd_TAG], ,
+[DUNE_VAR_APPEND([DUNE_CPPFLAGS], [" $3"])
+DUNE_VAR_APPEND([DUNE_LDFLAGS], [" $4"])
+
+# add flags to the deprecated DUNE_PKG_* family as well
+DUNE_VAR_APPEND([DUNE_PKG_CPPFLAGS], [" $3"])
+DUNE_VAR_APPEND([DUNE_PKG_LDFLAGS], [" $4"])
+DUNE_PKG_LIBS="$5 $DUNE_PKG_LIBS"
+AS_VAR_SET([_dune_amd_TAG], [1])
+])
+AS_VAR_POPDEF([_dune_amd_TAG], [_dune_amd_tag_$2])dnl
+])
+
+AC_DEFUN([DUNE_DISABLE_LIBCHECK],[
+ # hidden feature... --enable-dunelibcheck tells the dune module check to
+ # check only for the headers and not for the libs. This feature is used
+ # when building the web page, because we don't need the libs in this case
+
+ AC_ARG_ENABLE([dunelibcheck],[])
+])
+
+AC_DEFUN([DUNE_MODULE_ADD_SUMMARY_ENTRY],[
+ m4_pushdef([_dune_name], [$1])
+ m4_pushdef([_dune_module], [m4_translit(_dune_name, [-], [_])])
+ m4_pushdef([_DUNE_MODULE], [m4_toupper(_dune_module)])
+ AS_IF([test -n "$_DUNE_MODULE[]_VERSION" -a "x$with_[]_dune_module" != "xno"],[
+ result="version $_DUNE_MODULE[]_VERSION"
+ ],[
+ result="$with_[]_dune_module"
+ ])
+ DUNE_ADD_SUMMARY_MOD_ENTRY(_dune_name,[$result],[$_DUNE_MODULE[]_ROOT])
+])
+
+m4_define([_dune_sub_version],"`echo $1 | $AWK -F. -v FIELD=$2 '{ print int($FIELD) }'`")
+
+# DUNE_PARSE_MODULE_VERSION(NAME, VERSION)
+#
+# NAME Name of the module, lowercase with dashes (like "dune-common"). The
+# value must be known when autoconf runs, so shell variables in the
+# value are not permissible.
+# VERSION Version of the module. May contain shell variables. Numbers
+# seperated by ".".
+#
+# In the following, {MODULE} is the uppercase version of {NAME} with any "-"
+# replaced by "_".
+#
+# configure/shell variables and preprocessor defines:
+# {MODULE}_VERSION (complete version, same as {VERSION})
+# {MODULE}_VERSION_MAJOR (first component of {VERSION})
+# {MODULE}_VERSION_MINOR (second component of {VERSION})
+# {MODULE}_VERSION_REVISION (third component of {VERSION})
+AC_DEFUN([DUNE_PARSE_MODULE_VERSION],[
+ AC_REQUIRE([AC_PROG_AWK])
+
+ m4_pushdef([_dune_name], [$1])
+ m4_pushdef([_dune_version], [$2])
+ m4_pushdef([_dune_module], [m4_translit(_dune_name, [-], [_])])
+ m4_pushdef([_DUNE_MODULE], [m4_toupper(_dune_module)])
+
+ AC_SUBST(_DUNE_MODULE[]_VERSION,_dune_version)
+ AC_SUBST(_DUNE_MODULE[]_VERSION_MAJOR,_dune_sub_version(_dune_version,1))
+ AC_SUBST(_DUNE_MODULE[]_VERSION_MINOR,_dune_sub_version(_dune_version,2))
+ AC_SUBST(_DUNE_MODULE[]_VERSION_REVISION,_dune_sub_version(_dune_version,3))
+ AC_SUBST(DUNE_MOD_VERSION_MAJOR,_dune_sub_version(_dune_version,1))
+ AC_SUBST(DUNE_MOD_VERSION_MINOR,_dune_sub_version(_dune_version,2))
+ AC_SUBST(DUNE_MOD_VERSION_REVISION,_dune_sub_version(_dune_version,3))
+
+ AC_DEFINE_UNQUOTED(_DUNE_MODULE[]_VERSION, "_dune_version", [Define to the version of] _dune_name)
+ AC_DEFINE_UNQUOTED(_DUNE_MODULE[]_VERSION_MAJOR, $_DUNE_MODULE[]_VERSION_MAJOR, [Define to the major version of] _dune_name)
+ AC_DEFINE_UNQUOTED(_DUNE_MODULE[]_VERSION_MINOR, $_DUNE_MODULE[]_VERSION_MINOR, [Define to the minor version of] _dune_name)
+ AC_DEFINE_UNQUOTED(_DUNE_MODULE[]_VERSION_REVISION, $_DUNE_MODULE[]_VERSION_REVISION, [Define to the revision of] _dune_name)
+
+ m4_popdef([_DUNE_MODULE])
+ m4_popdef([_dune_module])
+ m4_popdef([_dune_version])
+ m4_popdef([_dune_name])
+])
+
+# DUNE_CHECK_MODULES(NAME, HEADER, SYMBOL)
+#
+# Generic check for dune modules. This macro should not be used directly, but
+# in the modules m4/{module}.m4 in the {MODULE}_CHECK_MODULE macro. The
+# {MODULE}_CHECK_MODULE macro knows the parameters to call this
+# DUNE_CHECK_MODULES macro with, and it does not take any parameters itself,
+# so it may be used with AC_REQUIRE.
+#
+# NAME Name of the module, lowercase with dashes (like "dune-common"). The
+# value must be known when autoconf runs, so shell variables in the
+# value are not permissible.
+#
+# HEADER Header to check for. The check will really be for <dune/{HEADER}>,
+# so the header must reside within a directory called "dune".
+#
+# SYMBOL Symbol to check for in the module's library. If this argument is
+# empty or missing, it is assumed that the module does not provide a
+# library. The value must be known when autoconf runs, so shell
+# variables in the value are not permissible. This value is actually
+# handed to AC_LINK_IFELSE/AC_LANG_PROGRAM unchanged as the
+# FUNCTION-BODY argument, so it may contain more complex stuff than a
+# simple symbol.
+#
+# The name of the library is assumed to be the same as the module name,
+# with any occurance of "-" removed. The path of the library is
+# obtained from pkgconfig for installed modules, or assumed to be the
+# directory "lib" within the modules root for non-installed modules.
+#
+# In the following, {module} is {NAME} with any "-" replaced by "_" and
+# {MODULE} is the uppercase version of {module}.
+#
+# configure options:
+# --with-{NAME}
+#
+# configure/shell variables:
+# {MODULE}_ROOT, {MODULE}_LIBDIR
+# HAVE_{MODULE} (1 or 0)
+# with_{module} ("yes" or "no")
+# DUNE_CPPFLAGS, DUNE_LDFLAGS, DUNE_LIBS (adds the modules values here,
+# substitution done by DUNE_CHECK_ALL)
+# ALL_PKG_CPPFLAGS, ALL_PKG_LDFLAGS, ALL_PKG_LIBS (adds the modules values
+# here, substitution done by DUNE_CHECK_ALL)
+# DUNE_PKG_CPPFLAGS, DUNE_PKG_LDFLAGS, DUNE_PKG_LIBS (deprecated, adds the
+# modules values here)
+# {MODULE}_VERSION
+# {MODULE}_VERSION_MAJOR
+# {MODULE}_VERSION_MINOR
+# {MODULE}_VERSION_REVISION
+#
+# configure substitutions/makefile variables:
+# {MODULE}_CPPFLAGS, {MODULE}_LDFLAGS, {MODULE}_LIBS
+# {MODULE}_ROOT
+# {MODULE}_LIBDIR (only if modules provides a library)
+#
+# preprocessor defines:
+# HAVE_{MODULE} (1 or undefined)
+# {MODULE}_VERSION
+# {MODULE}_VERSION_MAJOR
+# {MODULE}_VERSION_MINOR
+# {MODULE}_VERSION_REVISION
+#
+# automake conditionals:
+# HAVE_{MODULE}
+AC_DEFUN([DUNE_CHECK_MODULES],[
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_REQUIRE([AC_PROG_CXXCPP])
+ AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+ AC_REQUIRE([DUNE_DISABLE_LIBCHECK])
+ AC_REQUIRE([LT_OUTPUT])
+
+ # ____DUNE_CHECK_MODULES_____ ($1)
+
+ m4_pushdef([_dune_name], [$1])
+ m4_pushdef([_dune_module], [m4_translit(_dune_name, [-], [_])])
+ m4_pushdef([_dune_header], [$2])
+ m4_pushdef([_dune_ldpath], [lib])
+ m4_pushdef([_dune_lib], [m4_translit(_dune_name, [-], [])])
+ m4_pushdef([_dune_symbol], [$3])
+ m4_pushdef([_DUNE_MODULE], [m4_toupper(_dune_module)])
+
+ # switch tests to c++
+ AC_LANG_PUSH([C++])
+
+ # the usual option...
+ AC_ARG_WITH(_dune_name,
+ AS_HELP_STRING([--with-_dune_name=PATH],[_dune_module directory]))
+
+ # backup of flags
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ ac_save_LIBS="$LIBS"
+ ac_save_LDFLAGS="$LDFLAGS"
+ CPPFLAGS=""
+ LIBS=""
+
+ # if DUNE_LDFLAGS have a pre-assigned value (e.g. -all-static),
+ # also store it in DUNE_LDFLAGS_TMP to be consistent with DUNE_LDFLAGS
+ # the same holds for the other TMP variables, this is only to be done
+ # if these TMP variables are empty to avoid double apprearance
+ if test "x$DUNE_LDFLAGS_TMP" = "x"; then
+ DUNE_LDFLAGS_TMP="$DUNE_LDFLAGS"
+ fi
+ if test "x$DUNE_CPPFLAGS_TMP" = "x"; then
+ DUNE_CPPFLAGS_TMP="$DUNE_CPPFLAGS"
+ fi
+ if test "x$DUNE_LIBS_TMP" = "x"; then
+ DUNE_LIBS_TMP="$DUNE_LIBS"
+ fi
+
+ ##
+ ## Where is the module $1?
+ ##
+
+ AC_MSG_CHECKING([for $1 installation or source tree])
+
+ # is a directory set?
+ AS_IF([test -z "$with_[]_dune_module"],[
+ #
+ # initialize variables for lib
+ #
+ _DUNE_MODULE[]_LIBDIR=""
+ _dune_cm_LDFLAGS=""
+ _dune_cm_LIBS=""
+ #
+ # search module $1 via pkg-config
+ #
+ with_[]_dune_module="global installation"
+ AS_IF([test -z "$PKG_CONFIG"],[
+ AC_MSG_RESULT([failed])
+ AC_MSG_NOTICE([could not search for module _dune_name])
+ AC_MSG_ERROR([pkg-config is required for using installed modules])
+ ])
+ AS_IF(AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]),[
+ _dune_cm_CPPFLAGS="`$PKG_CONFIG --cflags _dune_name` -I./" 2>/dev/null
+ _DUNE_MODULE[]_ROOT="`$PKG_CONFIG --variable=prefix _dune_name`" 2>/dev/null
+ _DUNE_MODULE[]_VERSION="`$PKG_CONFIG --modversion _dune_name`" 2>/dev/null
+ _DUNE_MODULE[]_LIBDIR=`$PKG_CONFIG --variable=libdir _dune_name 2>/dev/null`
+ _dune_cm_LIBS=`$PKG_CONFIG --libs _dune_name 2>/dev/null`
+ HAVE_[]_DUNE_MODULE=1
+ AC_MSG_RESULT([global installation in $_DUNE_MODULE[]_ROOT])
+ ],[
+ HAVE_[]_DUNE_MODULE=0
+ AC_MSG_RESULT([not found])
+ ])
+ ],[
+ #
+ # path for module $1 is specified via command line
+ #
+ AS_IF([test -d "$with_[]_dune_module"],[
+ # expand tilde / other stuff
+ _DUNE_MODULE[]_ROOT=`cd "$with_[]_dune_module" && pwd`
+ _DUNE_MODULE[]_LIBDIR="$_DUNE_MODULE[]_ROOT/lib"
+
+ # expand search path (otherwise empty CPPFLAGS)
+ AS_IF([test -d "$_DUNE_MODULE[]_ROOT/include/dune"],[
+ # Dune was installed into directory given by with-dunecommon
+ _dune_cm_CPPFLAGS="-I$_DUNE_MODULE[]_ROOT/include"
+ _DUNE_MODULE[]_BUILDDIR=_DUNE_MODULE[]_ROOT
+ _DUNE_MODULE[]_VERSION="`PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$_DUNE_MODULE[]_ROOT/lib/pkgconfig $PKG_CONFIG --modversion _dune_name`" 2>/dev/null
+ _dune_cm_LIBS="-L$_DUNE_MODULE[]_LIBDIR -l[]_dune_lib"
+ ],[
+ _DUNE_MODULE[]_SRCDIR=$_DUNE_MODULE[]_ROOT
+ echo "testing $_DUNE_MODULE[]_ROOT/CMakeCache.txt"
+ # extract src and build path from Makefile or CMakeCache.txt, if found
+ AS_IF([test -f "$_DUNE_MODULE[]_ROOT/CMakeCache.txt"],[
+ _DUNE_MODULE[]_SRCDIR="`sed -ne '/^[]_dune_name[]_SOURCE_DIR:STATIC=/{s/^[]_dune_name[]_SOURCE_DIR:STATIC=//; p;}' "$_DUNE_MODULE[]_ROOT/CMakeCache.txt"`"
+ echo srcdir=$_DUNE_MODULE[]_SRCDIR
+ ],[test -f "$_DUNE_MODULE[]_ROOT/Makefile"],[
+ _DUNE_MODULE[]_SRCDIR="`sed -ne '/^abs_top_srcdir = /{s/^abs_top_srcdir = //; p;}' "$_DUNE_MODULE[]_ROOT/Makefile"`"
+ ])
+ _dune_cm_CPPFLAGS="-I$_DUNE_MODULE[]_SRCDIR"
+ _DUNE_MODULE[]_VERSION="`grep Version "$_DUNE_MODULE[]_SRCDIR/dune.module" | sed -e 's/^Version: *//'`" 2>/dev/null
+ AS_IF([test -f "$_DUNE_MODULE[]_LIBDIR[]/lib[]_dune_lib[].la"], [
+ # local modules is linked directly via the .la file
+ _dune_cm_LIBS="$_DUNE_MODULE[]_LIBDIR[]/lib[]_dune_lib[].la"],[
+ # No libtool file. This indicates a module build with CMake. Fall back to direct linking
+ _dune_cm_LIBS="-L$_DUNE_MODULE[]_LIBDIR[]/ -l[]_dune_lib[]"
+ ])
+ ])
+ # set expanded module path
+ with_[]_dune_module="$_DUNE_MODULE[]_ROOT"
+ HAVE_[]_DUNE_MODULE=1
+ AC_MSG_RESULT([found in $_DUNE_MODULE[]_ROOT])
+ ],[
+ HAVE_[]_DUNE_MODULE=0
+ AC_MSG_RESULT([not found])
+ AC_MSG_ERROR([_dune_name-directory $with_[]_dune_module does not exist])
+ ])
+ ])
+
+ CPPFLAGS="$ac_save_CPPFLAGS $DUNE_CPPFLAGS_TMP $DUNE_PKG_CPPFLAGS $_dune_cm_CPPFLAGS"
+ ##
+ ## check for an arbitrary header
+ ##
+ AC_CHECK_HEADER([dune/[]_dune_header],
+ [HAVE_[]_DUNE_MODULE=1],
+ [HAVE_[]_DUNE_MODULE=0
+ AS_IF([test -n "$_DUNE_MODULE[]_ROOT"],[
+ AC_MSG_WARN([$_DUNE_MODULE[]_ROOT does not seem to contain a valid _dune_name (dune/[]_dune_header not found)])
+ ])
+ ]
+ )
+
+ ##
+ ## check for lib (if lib name was provided)
+ ##
+ ifelse(_dune_symbol,,
+ # clear libs flags and inform the user
+ _DUNE_MODULE[]_LIBDIR=""
+ _dune_cm_LIBS=""
+ AC_MSG_NOTICE([_dune_name does not provide libs]),
+
+ AS_IF([test "x$enable_dunelibcheck" = "xno"],[
+ AC_MSG_WARN([library check for _dune_name is disabled. DANGEROUS!])
+ ],[
+ AS_IF([test "x$HAVE_[]_DUNE_MODULE" = "x1"],[
+ # save current LDFLAGS
+ ac_save_CXX="$CXX"
+ AC_CACHE_CHECK([for lib[]_dune_lib], dune_cv_lib[]_dune_lib, [
+ # Use $CXX $DUNE_LDFLAGS_TMP as link command, as the latter might
+ # contain the -static option to force static linkage
+ ac_cxx_ld=`echo $ac_save_CXX | sed -e "s@$CXX@$CXX $DUNE_LDFLAGS_TMP@"`
+
+ # define LTCXXLINK like it will be defined in the Makefile
+ CXX="./libtool --tag=CXX --mode=link $ac_cxx_ld "
+
+ # use module LDFLAGS
+ LDFLAGS="$ac_save_LDFLAGS $DUNE_PKG_LDFLAGS $_dune_cm_LDFLAGS"
+ LIBS="$_dune_cm_LIBS $DUNE_LIBS_TMP $LIBS"
+
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#]include<dune/[]_dune_header>],
+ [[_dune_symbol]])],
+ [dune_cv_lib[]_dune_lib=yes],
+ [dune_cv_lib[]_dune_lib=no])
+ ])
+
+ AS_IF([test "x$dune_cv_lib[]_dune_lib" = "xyes"], [
+ HAVE_[]_DUNE_MODULE=1
+ ],[
+ HAVE_[]_DUNE_MODULE=0
+ AS_IF([test -n "$_DUNE_MODULE[]_ROOT"],[
+ AC_MSG_WARN([$with_[]_dune_module does not seem to contain a valid _dune_name (failed to link with lib[]_dune_lib[].la)])
+ ])
+ ])
+ ])
+
+ # reset variables
+ CXX="$ac_save_CXX"
+ ])
+ )
+
+ # did we succeed?
+ AS_IF([test "x$HAVE_[]_DUNE_MODULE" = "x1"],[
+ # add the module's own flags and libs to the modules and the global
+ # variables
+ DUNE_ADD_MODULE_DEPS(m4_defn([_dune_name]), m4_defn([_dune_name]),
+ [$_dune_cm_CPPFLAGS], [$_dune_cm_LDFLAGS], [$_dune_cm_LIBS])
+
+ # set variables for our modules
+ AC_SUBST(_DUNE_MODULE[]_CPPFLAGS, "$_dune_cm_CPPFLAGS")
+ AC_SUBST(_DUNE_MODULE[]_LDFLAGS, "$_dune_cm_LDFLAGS")
+ AC_SUBST(_DUNE_MODULE[]_LIBS, "$_dune_cm_LIBS")
+ AC_SUBST(_DUNE_MODULE[]_ROOT, "$_DUNE_MODULE[]_ROOT")
+ ifelse(m4_defn([_dune_symbol]),,
+ [],
+ [AC_SUBST(_DUNE_MODULE[]_LIBDIR)
+ ])
+ AC_DEFINE(HAVE_[]_DUNE_MODULE, 1, [Define to 1 if] _dune_name [was found])
+
+ DUNE_PARSE_MODULE_VERSION(_dune_name, $_DUNE_MODULE[]_VERSION)
+
+ # set DUNE_* variables
+ # This should actually be unneccesary, but I'm keeping it in here for now
+ # for backward compatibility
+ DUNE_CPPFLAGS="$DUNE_CPPFLAGS \${_DUNE_MODULE[]_CPPFLAGS}"
+ DUNE_LDFLAGS="$DUNE_LDFLAGS \${_DUNE_MODULE[]_LDFLAGS}"
+ DUNE_LIBS="\${_DUNE_MODULE[]_LIBS} $DUNE_LIBS"
+
+ # the TMP version is used during the checks
+ DUNE_CPPFLAGS_TMP="$DUNE_CPPFLAGS_TMP $_DUNE_MODULE[]_CPPFLAGS"
+ DUNE_LDFLAGS_TMP="$DUNE_LDFLAGS_TMP $_DUNE_MODULE[]_LDFLAGS"
+ DUNE_LIBS_TMP="$_DUNE_MODULE[]_LIBS $DUNE_LIBS_TMP"
+
+ # add to global list
+ # only add my flags other flags are added by other packages
+ DUNE_PKG_CPPFLAGS="$DUNE_PKG_CPPFLAGS $_DUNE_MODULE[]_CPPFLAGS"
+ DUNE_PKG_LIBS="$DUNE_PKG_LIBS $LIBS"
+ DUNE_PKG_LDFLAGS="$DUNE_PKG_LDFLAGS $_DUNE_MODULE[]_LDFLAGS"
+
+ with_[]_dune_module="yes"
+ ],[
+ with_[]_dune_module="no"
+ ])
+
+ AM_CONDITIONAL(HAVE_[]_DUNE_MODULE, test x$HAVE_[]_DUNE_MODULE = x1)
+
+ # reset previous flags
+ CPPFLAGS="$ac_save_CPPFLAGS"
+ LDFLAGS="$ac_save_LDFLAGS"
+ LIBS="$ac_save_LIBS"
+
+ # add this module to DUNE_SUMMARY
+ DUNE_MODULE_ADD_SUMMARY_ENTRY(_dune_name)
+
+ # remove local variables
+ m4_popdef([_dune_name])
+ m4_popdef([_dune_module])
+ m4_popdef([_dune_header])
+ m4_popdef([_dune_ldpath])
+ m4_popdef([_dune_lib])
+ m4_popdef([_dune_symbol])
+ m4_popdef([_DUNE_MODULE])
+
+ # restore previous language settings (leave C++)
+ AC_LANG_POP([C++])
+])
--- /dev/null
+## -*- autoconf -*-
+# $Id$
+
+# this meta-check calls everything needed for Dune to work and all
+# possible components. Applications should use this so that
+# Dune-updates enable new features automagically
+
+# the entries are more or less copied from an "autoscan"-run in the
+# dune-directory
+AC_DEFUN([DUNE_CHECK_ALL],[
+ # doxygen and latex take a lot of time...
+ AC_REQUIRE([DUNE_DOCUMENTATION])
+
+ # check the compilers (before using libtool !!!)
+ AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+ AC_REQUIRE([AC_PROG_CC])
+ AC_REQUIRE([AC_PROG_CPP])
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_REQUIRE([AC_PROG_CXXCPP])
+ AC_REQUIRE([DUNE_SYNC_FC_F77])
+ AC_REQUIRE([AC_PROG_F77])
+ AC_REQUIRE([AC_PROG_FC])
+ # don't build shared libs per default, this is way better for debugging...
+ AC_REQUIRE([AC_DISABLE_SHARED])
+ # we need libtool
+dnl do not use LT_INIT since we want to be compatible with libtool 1.5
+ AC_REQUIRE([AC_PROG_LIBTOOL])
+ AC_REQUIRE([LT_COMPAT])
+
+ dnl check dependencies of this module
+ dnl this test is autogenerated for each module
+ AC_REQUIRE([DUNE_CHECK_MOD_DEPENDENCIES])
+
+ # convenience-variables if every found package should be used
+ AC_SUBST([ALL_PKG_LIBS], "$ALL_PKG_LIBS $LIBS")
+ AC_SUBST([ALL_PKG_LDFLAGS], "$LDFLAGS $ALL_PKG_LDFLAGS")
+ AC_SUBST([ALL_PKG_CPPFLAGS], "$CPPFLAGS $ALL_PKG_CPPFLAGS")
+
+ # convenience variables for all basic dune packages without extras
+ AC_SUBST([DUNE_CPPFLAGS])
+ AC_SUBST([DUNE_LDFLAGS])
+ AC_SUBST([DUNE_LIBS])
+
+ AC_SUBST([ACLOCAL_AMFLAGS], "$ACLOCAL_AMFLAGS")
+
+ AC_SUBST([abs_srcdir])
+ AC_SUBST([abs_top_srcdir])
+ AC_SUBST([abs_builddir])
+ AC_SUBST([abs_top_builddir])
+ AC_SUBST(am_dir, $DUNE_COMMON_ROOT/am)
+])
+
+AC_DEFUN([DUNE_ADD_SUMMARY_ENTRY],[
+ indentlen=24
+ txt="$1"
+ while test `echo "$txt" | tr -d '\n' | wc -c` -lt $indentlen; do txt="$txt."; done
+ txt="$txt: $2"
+ [DUNE_SUMMARY="$DUNE_SUMMARY echo '$txt';"]
+ fulltxt="$txt"
+ AS_IF([ test "x$3" != "x" ],[ fulltxt="$fulltxt ($3)" ])
+ [DUNE_FULLSUMMARY="$DUNE_FULLSUMMARY echo '$fulltxt';"]
+])
+
+AC_DEFUN([DUNE_ADD_SUMMARY_MOD_ENTRY],[
+ indentlen=24
+ txt=$1
+ while test `echo $txt | tr -d '\n' | wc -c` -lt $indentlen; do txt=$txt.; done
+ txt="$txt: $2"
+ [DUNE_MODULES_SUMMARY="$DUNE_MODULES_SUMMARY echo '$txt';"]
+ fulltxt="$txt"
+ AS_IF([ test "x$3" != "x" ],[ fulltxt="$fulltxt ($3)" ])
+ [DUNE_MODULES_FULLSUMMARY="$DUNE_MODULES_FULLSUMMARY echo '$fulltxt';"]
+])
+
+AC_DEFUN([DUNE_SUMMARY_ALL],[
+ # show search results
+ AC_REQUIRE([DUNE_OFFICIAL_TARBALLS])
+
+ echo
+ echo "Found the following Dune-components: "
+ echo
+ echo "----------------------------------------"
+ echo
+ [(eval $DUNE_MODULES_SUMMARY) | sort]
+ [(eval $DUNE_SUMMARY) | sort]
+ echo
+ echo "----------------------------------------"
+ echo
+
+ AS_IF([test "x$enable_officialtarballs" = "xyes"],[
+ echo Dune official tarball mode!
+ echo
+ echo "----------------------------------------"
+ echo
+ ])
+
+ echo "See ./configure --help and config.log for reasons why a component wasn't found"
+ echo
+
+ {
+ echo
+ echo "------------------------------------------------------------------------------"
+ echo "- SUMMARY -"
+ echo "------------------------------------------------------------------------------"
+ echo
+ [(eval $DUNE_MODULES_FULLSUMMARY) | sort]
+ echo
+ [(eval $DUNE_FULLSUMMARY) | sort]
+ echo
+ echo "------------------------------------------------------------------------------"
+ echo
+ } >&AS_MESSAGE_LOG_FD
+])
+
+AC_DEFUN([DUNE_OFFICIAL_TARBALLS],[
+ AC_ARG_ENABLE(officialtarballs,
+ AS_HELP_STRING([--enable-officialtarballs],[enforce configuration necessary for official tarballs]))
+])
--- /dev/null
+#
+# Add configure flags needed to create log files for dune-autobuild
+#
+
+AC_DEFUN([DUNE_AUTOBUILD_FLAGS],[
+ # special settings for check-log
+ AC_ARG_WITH([hostid],
+ AS_HELP_STRING([--with-hostid=HOST_IDENTIFIER],
+ [host identifier used for automated test runs]))
+ AS_IF([test "x$with_hostid" = "xno"],[
+ with_hostid="$ac_hostname (`uname -sm`, $COMPILER_NAME)";
+ ])
+
+ AC_SUBST([hostid], [$with_hostid])
+ AC_ARG_WITH([tag],
+ AS_HELP_STRING([--with-tag=TAG],
+ [tag to use for automated test runs]))
+ AS_IF([test "x$with_tag" = "xno"],[
+ with_tag=foo
+ ])
+ AC_SUBST([tag], [$with_tag])
+ AC_ARG_WITH([revision],
+ AS_HELP_STRING([--with-revision=TAG],
+ [revision to use for automated test runs]))
+ AS_IF([test "x$with_revision" = "xno"],[
+ with_revision=bar])
+ AC_SUBST([revision], [$with_revision])
+])
\ No newline at end of file
--- /dev/null
+# SYNOPSIS
+#
+# DUNE_BOOST_BASE([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# DESCRIPTION
+#
+# Test for the Boost C++ libraries of a particular version (or newer)
+#
+# If no path to the installed boost library is given the macro searchs
+# under /usr, /usr/local, /opt and /opt/local and evaluates the
+# $BOOST_ROOT environment variable. Further documentation is available at
+# <http://randspringer.de/boost/index.html>.
+#
+# This macro calls:
+#
+# AX_BOOST_BASE / AC_SUBST(BOOST_CPPFLAGS) / AC_SUBST(BOOST_LDFLAGS)
+#
+# And sets:
+#
+# HAVE_DUNE_BOOST
+# ENABLE_BOOST or undefined. Whether boost was found. The correct way to
+# to check this is "#if HAVE_BOOST": This way boost features will be disabled
+# unless ${BOOST_CPPFLAGS} was given when compiling
+#serial 1
+AC_DEFUN([DUNE_BOOST_BASE],
+[
+AX_BOOST_BASE([$1],[
+ AC_DEFINE(HAVE_DUNE_BOOST, [ENABLE_BOOST],[Define to ENABLE_BOOST if the Boost library is available])
+ BOOST_CPPFLAGS="$BOOST_CPPFLAGS -DENABLE_BOOST"
+ AC_SUBST(BOOST_CPPFLAGS)
+ # execute ACTION-IF-FOUND (if present):
+ ifelse([$2], , :, [$2])
+],[
+ # execute ACTION-IF-NOT-FOUND (if present):
+ ifelse([$3], , :, [$3])
+])])
\ No newline at end of file
--- /dev/null
+dnl -*- autoconf -*-
+# DUNE_CHECK_LIB_EXT(PATH, LIBRARY, FUNCTION, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND], [OTHER-LIBRARIES])
+#
+# Just like AC_CHECK_LIB, but it allows a library path to be specified. The
+# default ACTION-IF-FOUND is extended to also add that library path to LIBS.
+#
+# PATH Path to search for the library. This should be something suitable
+# to be used inside a double quoted shell string.
+#
+# LIBRARY Name of the library. This should be something suitable to be used
+# inside a double quoted shell string. If this containes shell
+# subtitutions, no config.h template will be generated by the default
+# action.
+#
+# FUNCTION Function to check for. This should be something suitable to be
+# used inside a double quoted shell string.
+#
+# ACTION-IF-FOUND Action to perform when the library was found. If empty, set
+# prepend "-L{PATH} -l{LIBRARY}" and create a preprocessor define
+# HAVE_LIB{LIBRARY} (the preprocessor define's name is passed through
+# AS_TR_CPP to make it suitable first).
+#
+# ACTION-IF-NOT-FOUND Action to perform when the library was not found.
+#
+# OTHER-LIBRARIES If linking agains LIBRARY will only succeed in the presence
+# of other libraries not already in LIBS, specify them here. These
+# libraries will not be added to LIBS in the default ACTION-IF-FOUND.
+AC_DEFUN([DUNE_CHECK_LIB_EXT],
+[m4_ifval([$4], , [AH_TEMPLATE(AS_TR_CPP([HAVE_LIB$2]),
+ [Define to 1 if you have the `$2' library (-L$1 -l$2).])])dnl
+AS_VAR_PUSHDEF([dune_Lib],
+ [dune_cv_lib_$1]AS_LITERAL_IF([$1], , [['']])dnl
+[_$2]AS_LITERAL_IF([$2], , [['']])dnl
+[_$3])dnl
+AC_CACHE_CHECK([for $3 in -L$1 -l$2], dune_Lib,
+[dune_check_lib_ext_save_LIBS=$LIBS
+LIBS="-L$1 -l$2 $6 $LIBS"
+AC_LINK_IFELSE([AC_LANG_CALL([], [$3])],
+ [AS_VAR_SET(dune_Lib, [yes])],
+ [AS_VAR_SET(dune_Lib, [no])])
+LIBS=$dune_check_lib_ext_save_LIBS])
+DUNE_VAR_IF([dune_Lib], [yes],
+ [m4_default([$4], [AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE_LIB$2]))
+ LIBS="-L$1 -l$2 $LIBS"
+])],
+ [$5])
+AS_VAR_POPDEF([dune_Lib])dnl
+])# DUNE_CHECK_LIB_EXT
--- /dev/null
+AC_DEFUN([DUNE_COMMON_CHECKS],
+[
+ AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+
+ AC_REQUIRE([AC_PROG_CC])
+ AC_REQUIRE([AC_PROG_CPP])
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_REQUIRE([AC_PROG_CXXCPP])
+ AC_REQUIRE([AC_PROG_INSTALL])
+ AC_REQUIRE([AC_PROG_LN_S])
+ AC_REQUIRE([AC_PROG_MAKE_SET])
+ AC_REQUIRE([AC_PROG_RANLIB])
+ AC_REQUIRE([AC_PROG_LIBTOOL])
+ AC_REQUIRE([AC_PROG_AWK])
+ AC_REQUIRE([ACX_LAPACK])
+ AC_REQUIRE([AC_FC_WRAPPERS])
+ # defined $(MKDIR_P), which is required during install
+ AC_REQUIRE([AC_PROG_MKDIR_P])
+
+ AC_REQUIRE([DUNE_CHECK_COMPILER])
+ AC_REQUIRE([GXX0X])
+ AC_REQUIRE([STATIC_ASSERT_CHECK])
+ AC_REQUIRE([NULLPTR_CHECK])
+ AC_REQUIRE([SHARED_PTR])
+ AC_REQUIRE([VARIADIC_TEMPLATES_CHECK])
+ AC_REQUIRE([RVALUE_REFERENCES_CHECK])
+ AC_REQUIRE([INITIALIZER_LIST_CHECK])
+ AC_REQUIRE([CXX11_CONDITIONAL_CHECK])
+ AC_REQUIRE([CXX11_CONSTEXPR_CHECK])
+ AC_REQUIRE([DUNE_BOOST_BASE])
+ AC_REQUIRE([MAKE_SHARED])
+ AC_REQUIRE([DUNE_LINKCXX])
+ AC_REQUIRE([DUNE_CHECKDEPRECATED])
+ AC_REQUIRE([DUNE_CHECKUNUSED])
+ AC_REQUIRE([DUNE_CHECK_CXA_DEMANGLE])
+ AC_REQUIRE([DUNE_SET_MINIMAL_DEBUG_LEVEL])
+ AC_REQUIRE([DUNE_PATH_XDR])
+ AC_REQUIRE([DUNE_MPI])
+ AC_REQUIRE([DUNE_SYS_MPROTECT])
+ AC_REQUIRE([DUNE_TR1_HEADERS])
+
+ dnl check for programs
+ AC_REQUIRE([AC_PROG_CC])
+ # add -Wall if the compiler is gcc
+ AS_IF([test "x$ac_test_CFLAGS" != "xset" -a "x$GCC" = "xyes"],[
+ CFLAGS="$CFLAGS -Wall"
+ ])
+ # add -Wall if the compiler is g++
+ AC_REQUIRE([AC_PROG_CXX])
+ AS_IF([test "x$ac_test_CXXFLAGS" != "xset" -a "x$GXX" = "xyes"],[
+ CXXFLAGS="$CXXFLAGS -Wall"
+ ])
+
+ dnl checks for header files.
+ AC_REQUIRE([AC_HEADER_STDC])
+ AC_LANG_PUSH([C++])
+
+ AC_CHECK_HEADERS([malloc.h string.h])
+
+ AC_LANG_POP([C++])
+
+ dnl checks for typedefs, structures, and compiler characteristics.
+ # doesn't work, but we don't need it currently
+ # AC_REQUIRE([AC_HEADER_STDBOOL])
+ AC_REQUIRE([AC_C_CONST])
+ AC_REQUIRE([AC_C_INLINE])
+ AC_REQUIRE([AC_TYPE_SIZE_T])
+ AC_REQUIRE([AC_STRUCT_TM])
+
+ dnl check for library functions
+
+ AC_LANG_PUSH([C++])
+ AC_CHECK_LIB([m], [pow])
+ AC_CHECK_FUNCS([sqrt strchr])
+ AC_LANG_POP([C++])
+
+ AC_REQUIRE([DUNE_PATH_GMP])
+])
+
+AC_DEFUN([DUNE_COMMON_CHECK_MODULE],
+[
+ DUNE_CHECK_MODULES([dune-common], [common/stdstreams.hh],
+ [#ifndef DUNE_MINIMAL_DEBUG_LEVEL
+ #define DUNE_MINIMAL_DEBUG_LEVEL 1
+ #endif
+ Dune::derr.active();])
+])
--- /dev/null
+# $Id$
+# check for supported compilers
+
+AC_DEFUN([DUNE_CHECK_COMPILER],[
+
+AC_ARG_ENABLE(compilercheck,
+ AS_HELP_STRING([--disable-compilercheck],
+ [disable check for supported compilers]),
+ [compilercheck=$enableval], [compilercheck=yes])
+
+SUPPORTED_COMPILER="gcc (>= 4.1), should work with recent versions of icc and clang (>= 3.0)"
+
+AC_REQUIRE([AC_PROG_CXX])
+cat >conftest.cc <<_ACEOF
+#include <cstdio>
+
+#if defined __ICC && ! defined CXX_SUPPORTED
+ #if __ICC >= 700
+ #define CXX_SUPPORTED "icc %2.2f", 1.0*__ICC/100
+ #endif
+#endif
+#if defined __clang__ && ! defined CXX_SUPPORTED
+ #if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 0)
+ #define CXX_SUPPORTED \
+ "clang %i.%i.%i", __clang_major__, __clang_minor__, __clang_patchlevel__
+ #endif
+#endif
+#if defined __GNUC__ && ! defined CXX_SUPPORTED
+ #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
+ #define CXX_SUPPORTED \
+ "gcc %i.%i.%i", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__
+ #endif
+#endif
+#ifndef CXX_SUPPORTED
+ #error Your compiler is not officially supported by dune
+#endif
+int main() {
+ printf(CXX_SUPPORTED);
+ return 0;
+}
+_ACEOF
+
+AS_IF([test "x$compilercheck" = "xno"],
+ [AC_MSG_WARN([compilercheck is disabled. DANGEROUS!])],
+ [ AC_MSG_CHECKING([whether compiler is officially supported by DUNE])
+ AS_IF([$CXX conftest.cc -o conftest.$ac_exeext >&5],
+ [ AC_MSG_RESULT([yes])
+ COMPILER_NAME=`./conftest.$ac_exeext`;
+ rm -f conftest.$ac_exeext],
+ [ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([Your compiler is not officially supported by dune
+ dune is known to work with $SUPPORTED_COMPILER])
+ ])
+ ])
+
+AS_IF([test -z "$COMPILER_NAME"],[
+ COMPILER_NAME="unknown compiler"])
+])
--- /dev/null
+# Check if the compiler supports the abi::__cxa_demangle function required to
+# make the type names returned by typeid() human-readable
+AC_DEFUN([DUNE_CHECK_CXA_DEMANGLE],[
+ AC_CACHE_CHECK([for abi::__cxa_demangle], dune_cv_cxa_demangle, [
+ AC_LANG_PUSH([C++])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #include <cxxabi.h>
+ ]],
+ [[
+ int foobar = 0;
+ const char *foo = typeid(foobar).name();
+ int status;
+ char *demangled = abi::__cxa_demangle( foo, 0, 0, &status );
+ ]]
+ )],
+ dune_cv_cxa_demangle="yes",
+ dune_cv_cxa_demangle="no")
+ AC_LANG_POP([C++])
+ ])
+
+ AS_IF([test "x$dune_cv_cxa_demangle" = "xyes"],
+ [AC_DEFINE_UNQUOTED(HAVE_CXA_DEMANGLE,
+ 1,
+ [does the compiler support abi::__cxa_demangle])])
+])
--- /dev/null
+# $Id$
+
+# Check for the right way to create the deprecation warning
+
+AC_DEFUN([DUNE_CHECKDEPRECATED],[
+ AC_CACHE_CHECK([for __attribute__((deprecated))], dune_cv_attribute_deprecated, [
+ AC_LANG_PUSH([C++])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #define DEP __attribute__((deprecated))
+ class bar { bar() DEP; };
+ class peng { } DEP;
+ template <class T>
+ class t_bar { t_bar() DEP; };
+ template <class T>
+ class t_peng { t_peng() {}; } DEP;
+ void foo() DEP;
+ void foo() {};
+ ]],
+ [])],
+ dune_cv_attribute_deprecated="yes",
+ dune_cv_attribute_deprecated="no")
+ AC_LANG_POP([C++])
+ ])
+
+ AC_CACHE_CHECK([for __attribute__((deprecated("message")))],
+ dune_cv_attribute_deprecated_message, [
+ AC_LANG_PUSH([C++])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #define DEP __attribute__((deprecated("fireworks!")))
+ class bar { bar() DEP; };
+ class peng { } DEP;
+ template <class T>
+ class t_bar { t_bar() DEP; };
+ template <class T>
+ class t_peng { t_peng() {}; } DEP;
+ void foo() DEP;
+ void foo() {};
+ ]],
+ [])],
+ dune_cv_attribute_deprecated_message="yes",
+ dune_cv_attribute_deprecated_message="no")
+ AC_LANG_POP([C++])
+ ])
+
+ if test "$dune_cv_attribute_deprecated" = "yes"; then
+ AC_DEFINE_UNQUOTED(HAS_ATTRIBUTE_DEPRECATED, 1,
+ [does the compiler support __attribute__((deprecated))?])
+ fi
+
+ if test "$dune_cv_attribute_deprecated_message" = "yes"; then
+ AC_DEFINE_UNQUOTED(HAS_ATTRIBUTE_DEPRECATED_MSG, 1,
+ [does the compiler support __attribute__((deprecated("message"))?])
+ fi
+
+ AH_BOTTOM([#include <dune/common/deprecated.hh>])
+])
--- /dev/null
+dnl -*- autoconf -*-
+# Define configure substitution SUBSTITUTION. Assign value to it but add an
+# additional preprocessor define which may be detected by config.h. Add some
+# text to config.h which detects that define and issues the warning in
+# message.
+#
+# DUNE_DEPRECATED_CPPFLAGS(SUBSTITUTION, VALUE, MESSAGE)
+AC_DEFUN([DUNE_DEPRECATED_CPPFLAGS],
+[
+ AH_VERBATIM([DEPRECATED_$1_USED],
+[#ifdef DEPRECATED_$1_USED
+]dnl Note we have to use a quadrigraph in the following call to m4_text_wrap
+dnl since older versions of that macro are seriously broken when it comes to
+dnl the #-character
+m4_text_wrap([$3], [@%:@warning ])[
+#endif])
+ AC_SUBST([$1], [$2" -D DEPRECATED_$1_USED"])
+])
--- /dev/null
+# check for auxiliary tools so that it's not fatal if they're missing
+AC_DEFUN([DUNE_DOC_PROGS],[
+ AC_CHECK_PROGS([DOXYGEN], [doxygen], [true])
+ AM_CONDITIONAL([DOXYGEN], [test "x$DOXYGEN" != xtrue])
+ AC_CHECK_PROGS([TEX], [latex], [true])
+ AC_CHECK_PROGS([BIBTEX], [bibtex], [true])
+ AC_CHECK_PROGS([DVIPDF], [dvipdf], [true])
+ AC_CHECK_PROGS([DVIPS], [dvips], [true])
+ AC_CHECK_PROGS([WML], [wml], [true])
+ AM_CONDITIONAL([WML], [test "x$WML" != xtrue])
+ AC_CHECK_PROGS([DOT], [dot], [true])
+ AM_CONDITIONAL([DOT], [test "x$DOT" != xtrue])
+ AC_CHECK_PROGS([PERL], [perl], [true])
+ AC_REQUIRE([DUNE_INKSCAPE])
+ AC_CHECK_PROGS([CONVERT], [convert], [true])
+ AM_CONDITIONAL([CONVERT], [test "x$CONVERT" != xtrue])
+])
+
+# searches for documentation
+AC_DEFUN([DUNE_DOCUMENTATION],[
+
+ AC_REQUIRE([DUNE_OFFICIAL_TARBALLS])
+ AC_REQUIRE([DUNE_DOC_PROGS])
+ AC_REQUIRE([DUNE_WEB])
+
+ # official tarballs require all documentation programs
+ AS_IF([test "x$enable_officialtarballs" = "xyes"],[
+ AS_IF([test "x$DOXYGEN" = "xtrue"],[
+ AC_MSG_ERROR([doxygen is missing. This program is required for official tarballs!])])
+ AS_IF([test "x$LATEX" = "xtrue"],[
+ AC_MSG_ERROR([latex is missing. This program is required for official tarballs!])])
+ AS_IF([test "x$BIBTEX" = "xtrue"],[
+ AC_MSG_ERROR([bibtex is missing. This program is required for official tarballs!])])
+ AS_IF([test "x$DVIPDF" = "xtrue"],[
+ AC_MSG_ERROR([dvipdf is missing. This program is required for official tarballs!])])
+ AS_IF([test "x$DVIPS" = "xtrue"],[
+ AC_MSG_ERROR([dvips is missing. This program is required for official tarballs!])])
+ AS_IF([test "x$DOT" = "xtrue"],[
+ AC_MSG_ERROR([dot is missing. This program is required for official tarballs!])])
+ AS_IF([test "x$PERL" = "xtrue"],[
+ AC_MSG_ERROR([perl is missing. This program is required for official tarballs!])])
+ AS_IF([test "x$CONVERT" = "xtrue"],[
+ AC_MSG_ERROR([convert is missing. This program is required for official tarballs!])])
+ AS_IF([test "x$INKSCAPE" = xfalse || test "x$INKSCAPE" = xno],[
+ AC_MSG_ERROR([inkscape is missing. This program is required for official tarballs!])])
+ ])
+
+ # disable documentation rules
+ AC_ARG_ENABLE(documentation,
+ AS_HELP_STRING([--disable-documentation],[don\'t generate docs, speeds up the build]))
+ AS_IF([test "x$enable_officialtarballs" = "xyes"],[
+ # official tarballs require documentation
+ AS_IF([test "x$enable_documentation" = "xno"],[
+ AC_MSG_WARN([official tarballs require documentation, ignoring '--disable-documentation'!])
+ enable_documentation="yes"
+ ])
+ ])
+ AM_CONDITIONAL(BUILD_DOCS, [test "x$enable_documentation" != "xno"])
+
+])
+
+AC_DEFUN([DUNE_WEB],
+[
+ AC_REQUIRE([DUNE_OFFICIAL_TARBALLS])
+ AC_REQUIRE([DUNE_DOC_PROGS])
+
+ # special variable to include the documentation into the website
+ AC_ARG_WITH(duneweb,
+ AS_HELP_STRING([--with-duneweb=PATH],[Only needed for website-generation, path to checked out version of dune-web]))
+
+ AS_IF([test -n "$with_duneweb"],[
+
+ # disable dune-web in official tarball mode
+ AS_IF([test "x$enable_officialtarballs" = "xyes"],[
+ AC_MSG_WARN([ignoring dune-web... official tarballs enabled])
+ with_duneweb="no"
+ ])
+
+ # disable dune-web if wml or doxygen is missing
+ AS_IF([test "x$WML" = "xtrue"],[
+ AC_MSG_WARN([ignoring dune-web... wml missing])
+ with_duneweb="no"
+ ])
+ AS_IF([test "x$DOXYGEN" = "xtrue"],[
+ AC_MSG_WARN([ignoring dune-web... doxygen missing])
+ with_duneweb="no"
+ ])
+
+ AS_IF([test "x$with_duneweb" != "xno"],[
+ # parameter is set. Check it
+ AC_MSG_CHECKING([whether passed Dune-Web ($with_duneweb) directory appears correct])
+ WEBTESTFILE="$with_duneweb/layout/default.wml"
+ AS_IF([test -d "$with_duneweb" -a -e "$WEBTESTFILE"],[
+ AC_MSG_RESULT([ok])
+ # normalize path
+ with_duneweb=`(cd $with_duneweb && pwd)` ;
+ ],[
+ AS_IF([test -d "$with_duneweb"],[
+ AC_MSG_ERROR([$WEBTESTFILE not found in Dune-web dir $with_duneweb!])
+ ],[
+ AC_MSG_ERROR([Dune-Web directory $with_duneweb not found!])
+ ])
+ with_duneweb=no
+ ])
+ ])
+ DUNE_ADD_SUMMARY_ENTRY([dune web],[$with_duneweb])
+ ],[
+ with_duneweb=no
+ ])
+ AC_SUBST(DUNEWEBDIR, $with_duneweb)
+ AM_CONDITIONAL(DUNEWEB, [test "x$with_duneweb" != "xno"])
+])
--- /dev/null
+# a trick to make life for the user easier.
+#
+# some libs need the fortran test, while other use the f77 test. This
+# requires the user to provide two variables, usually with the same
+# parameter. In most cases the F77 compiler will be the same as teh FC
+# compiler.
+#
+# We test for FC and F77. If the user has specified both, we do
+# nothing, if the user has specified only one of them, we assume that
+# the compiler supports both and copy the value. Usually this should
+# be the sane default.
+#
+AC_DEFUN([DUNE_SYNC_FC_F77],[
+ # variant 1
+ # FC is set, while F77 is not set
+ AS_IF([test -n "$FC" && test -z "$F77"], [
+ AC_MSG_NOTICE([Fortran compiler FC (fortran 90) specified,
+ while F77 (fortran 77) wasn't set.
+ Trying to use FC as F77.])
+ F77="$FC"
+ ])
+ # variant 2
+ # F77 is set, while FC is not set
+ AS_IF([test -z "$FC" && test -n "$F77"], [
+ AC_MSG_NOTICE([Fortran compiler F77 (fortran 77) specified,
+ while FC (fortran 90) wasn't set.
+ Trying to use F77 as FC.])
+ FC="$F77"
+ ])
+])
+
--- /dev/null
+# $Id$
+# tries to link c++ objects
+
+AC_DEFUN([DUNE_LINKCXX],[
+
+AC_LANG_PUSH([C++])
+
+AC_MSG_CHECKING([whether compiling C++ code works])
+AC_COMPILE_IFELSE([
+ AC_LANG_SOURCE(
+ [ #include <iostream>
+ int main (int argc, char** argv) {
+ std::cout << std::endl;
+ }])],
+ [ AC_MSG_RESULT([yes]);
+ AC_MSG_CHECKING([whether linking C++ objects works]);
+ # link from object file
+ ac_old_link=$ac_link
+ ac_link=`echo "$ac_old_link" | sed "s/conftest\.$ac_ext/conftest\.$ac_objext/"`
+ # disable deletion of object file
+ ac_old_objext=$ac_objext;
+ ac_objext="";
+ AC_LINK_IFELSE([],
+ [ AC_MSG_RESULT([yes])],
+ [ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([Could not link C++ code])])
+ ac_objext=$ac_old_objext;
+ ac_link=$ac_old_link;],
+ [ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([Could not compile C++ code])]
+)
+
+AC_LANG_POP([C++])
+
+])
--- /dev/null
+dnl -*- autoconf -*-
+# $Id$
+
+# wrapper for the autoconf-archive check. Note: compiling MPI-stuff sucks!
+
+# Explanation:
+# ============
+#
+
+# Compilation of MPI programs is normally done by a
+# mpicc/mpiCC-wrapper that adds all options needed. Thus, it may seem
+# possible to just replace the compiler call by the wrapper and
+# everything works. Unfortunately that's not the case: automake and
+# libtool both show strange behaviour.
+#
+# In detail: replacing the compiler globally via ./configure CXX=mpiCC
+# should work (at least I've found reports claiming this) but that is
+# not what we want: mainly, it just adds a level of possible errors
+# (mpiCC from MPICH does _nothing_ if "mpicc -c dummy.cc" is called!)
+# and may introduce nice library-clashes.
+#
+# The next approach would be to include
+# if MPI
+# CXX = $(MPICXX)
+# endif
+# in the Makefile.am where MPI is needed. First, this will change
+# compilations of all binaries in this directory and secondly the
+# dependency-tracking seems to break: the first compilation worked but
+# the second failed with the compiler complaining about mismatching
+# flags... There is no 'program_CXX = ...' in automake but even if
+# there were it would break as well
+#
+# Thus, the best solution is to extract the flags needed for
+# compilation and linking. Unfortunately, the parameters and behaviour
+# of mpicc is not at all consistent over different
+# implementations. For MPICH the parameters -compile_info and
+# -link_info exist (albeit not being documented in the manpage, only
+# in -help), for LAM dummy-calls of compilation and linking together
+# with a -showme parameter (which is called -show in MPICH...) have to
+# be used. Obviously, we have to identify the type of package... this
+# is done via mpiCC-calls for now, I wouldn't be surprised if ths
+# breaks often. Bad luck. Blame the MPI folks for this mess. And blame
+# them a lot. [Thimo 26.8.2004]
+
+# Sometimes ACX_MPI will not be able to find the correct MPI compiler,
+# or sometimes you might have several MPI installations. Specify the
+# MPICC variable to enforce a certain MPI compiler.
+
+# In order to disable the usage of MPI (and make Dune purely
+# sequential) you can supply the option
+# --disable-parallel
+# [Christian 9.7.2006]
+
+# DUNE_MPI()
+#
+# With the help of ACX_MPI find the MPI compiler, and with the help of
+# MPI_CONFIG find the libraries and compiler and linker options necessary to
+# compile MPI programs with the standard compiler. Will set the following
+# things:
+#
+# configure shell variables:
+# MPICC
+# MPILIBS
+# DUNEMPICPPFLAGS
+# DUNEMPILDFLAGS
+# DUNEMPILIBS
+# dune_MPI_VERSION
+# with_mpi ("no" if MPI is missing, "yes" followed by some more details if
+# MPI is present)
+# ALL_PKG_CPPFLAGS (adds its stuff here)
+# ALL_PKG_LDFLAGS (adds its stuff here)
+# ALL_PKG_LIBS (adds its stuff here)
+#
+# configure substitutions/Makefile variables
+# MPICC
+# MPILIBS
+# DUNEMPICPPFLAGS
+# DUNEMPILDFLAGS
+# DUNEMPILIBS
+# MPI_VERSION (set from dune_MPI_VERSION)
+#
+# preprocessor defines
+# HAVE_MPI (defined when $with_mpi!=no)
+#
+# automake conditionals
+# MPI (true when $with_mpi!=no)
+AC_DEFUN([DUNE_MPI],[
+ AC_PREREQ(2.50) dnl for AC_LANG_CASE
+
+ # get compilation script
+ AC_LANG_CASE([C],[
+ dune_mpi_isgnu="$GCC"
+ ],
+ [C++],[
+ dune_mpi_isgnu="$GXX"
+ ])
+
+ AC_LANG_PUSH([C])
+
+ # enable/disable parallel features
+ AC_ARG_ENABLE(parallel,
+ AS_HELP_STRING([--enable-parallel],
+ [Enable the parallel features of Dune. If enabled
+ configure will try to determine your MPI automatically. You can
+ overwrite this setting by specifying the MPICC variable]))
+ AC_SUBST(ENABLE_PARALLEL, "$enable_parallel")
+
+ # disable runtest if we have a queuing system
+ AC_ARG_ENABLE(mpiruntest,
+ AS_HELP_STRING([--disable-mpiruntest],
+ [Don\'t try to run a MPI program during configure. (This is needed if you depend on a queuing system)]))
+
+ with_mpi="no"
+
+ ## do nothing if --disable-parallel is used
+ AS_IF([test "x$enable_parallel" = "xyes"],[
+ ACX_MPI([
+ MPICOMP="$MPICC"
+
+ MPI_CONFIG()
+ DUNEMPICPPFLAGS="$DUNEMPICPPFLAGS $MPI_NOCXXFLAGS -DENABLE_MPI=1"
+
+ with_mpi="yes ($dune_MPI_VERSION)"
+ ],[
+ # ACX_MPI didn't find anything
+ with_mpi="no"
+ ])])
+
+ # if an MPI implementation was found..
+ AS_IF([test "x$with_mpi" != "xno"],[
+ ### do a sanity check: can we compile and link a trivial MPI program?
+ AC_MSG_CHECKING([whether compiling with $dune_MPI_VERSION works])
+
+ # store old values
+ ac_save_LIBS="$LIBS"
+ ac_save_LDFLAGS="$LDFLAGS"
+ ac_save_CPPFLAGS="$CPPFLAGS"
+
+ # looks weird but as the -l... are contained in the MPI_LDFLAGS these
+ # parameters have to be last on the commandline: with LIBS this is true
+ LIBS="$DUNEMPILIBS $LIBS"
+ LDFLAGS="$LDFLAGS $DUNEMPILDFLAGS"
+ CPPFLAGS="$CPPFLAGS $DUNEMPICPPFLAGS"
+
+ # try to create MPI program
+ AC_LANG_PUSH([C++])
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [ #include <mpi.h>
+ int main (int argc, char** argv) {
+ MPI_Init(&argc, &argv);
+ MPI_Finalize(); }])],
+ [ AC_MSG_RESULT([yes]) ],
+ [ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([could not compile MPI testprogram!
+ See config.log for details])
+ with_mpi=no]
+ )
+
+ AC_MSG_CHECKING([whether MPI is recent enough (MPI-2.1)])
+ # check MPI version and issue a deprecation warning if MPI is older than 2.1
+ # TODO: Replace with error after 2.3 release
+ AC_LANG_PUSH([C++])
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [ #include <mpi.h>
+ #if !((MPI_VERSION > 2) || (MPI_VERSION == 2 && MPI_SUBVERSION >= 1))
+ fail with a horribe compilation error due to old MPI version
+ #endif
+ int main (int argc, char** argv) {
+ MPI_Init(&argc, &argv);
+ MPI_Finalize(); }])],
+ [ AC_MSG_RESULT([yes]) ],
+ [ AC_MSG_RESULT([no])
+ AC_MSG_WARN([You are using a very old version of MPI that
+ is not compatible with the MPI-2.1 standard. Support for your
+ version of MPI is deprecated and will be removed after the next
+ release!])
+ mpi_deprecated=yes]
+ )
+
+ AS_IF([test "x$mpiruntest" != "xyes"],[
+ AC_MSG_WARN([Disabled test whether running with $dune_MPI_VERSION works.])
+ ],[
+ AC_MSG_CHECKING([whether running with $dune_MPI_VERSION works])
+ AC_RUN_IFELSE(
+ [AC_LANG_SOURCE(
+ [ #include <mpi.h>
+ int main (int argc, char** argv) {
+ MPI_Init(&argc, &argv);
+ MPI_Finalize(); }])],
+ [ AC_MSG_RESULT([yes]) ],
+ [ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([could not run MPI testprogram!
+ Did you forget to setup your MPI environment?
+ Some MPI implementations require a special deamon to be running!
+ If you don't want to use MPI you can use --disable-parallel to disable
+ all parallel code in Dune.
+ If you want to use parallel code, but cannot run the MPI run test
+ during configure (This is needed if you depend on a queuing system), you
+ might use the --disable-mpiruntest switch.
+ See config.log for details])
+ with_mpi=no]
+ )
+ ])
+ AC_LANG_POP
+
+ # Check for MPI-2 Standard
+ # We have to provide a dummy lib here as we do not know what the name
+ # of the mpi is. -lm should be saved.
+ AC_CHECK_LIB(m,[MPI_Finalized], [AC_DEFINE(MPI_2, 1, [Define to 1 if MPI supports MPI-2])])
+
+ # restore variables
+ LIBS="$ac_save_LIBS"
+ CPPFLAGS="$ac_save_CPPFLAGS"
+ ])
+
+ # set flags
+ AS_IF([test "x$with_mpi" != "xno"],[
+ AC_DEFINE(HAVE_MPI,ENABLE_MPI,[Define if you have the MPI library.
+ This is only true if MPI was found by configure _and_ if the application
+ uses the DUNEMPICPPFLAGS (or the deprecated MPI_CPPFLAGS)])
+ ])
+ AC_SUBST(DUNEMPICPPFLAGS)
+ AC_SUBST(DUNEMPILDFLAGS)
+ AC_SUBST(DUNEMPILIBS)
+ AC_SUBST(MPI_VERSION, $dune_MPI_VERSION)
+
+ # NOTE: If you intent to copy-n-paste this line, try to avoid including any
+ # flags of dependent libraries that call DUNE_ADD_ALL_PKG themselves.
+ DUNE_ADD_ALL_PKG([MPI], [\${DUNEMPICPPFLAGS}], [\${DUNEMPILDFLAGS}], [\${DUNEMPILIBS}])
+
+ AM_CONDITIONAL(MPI, [test "x$with_mpi" != "xno"])
+
+ AS_IF([test "x$mpi_deprecated" == "xyes"],[
+ DUNE_ADD_SUMMARY_ENTRY([MPI],[$with_mpi (deprecated MPI version)])
+ ],[
+ DUNE_ADD_SUMMARY_ENTRY([MPI],[$with_mpi])
+ ])
+
+ AC_LANG_POP
+])
--- /dev/null
+# $Id: dune_deprecated.m4 1114 2004-11-17 14:00:06Z christi $
+
+# Set the minimal verbosity level. All stream with a level below will
+# get removed by the optimizer.
+
+AC_DEFUN([DUNE_SET_MINIMAL_DEBUG_LEVEL],[
+
+ # VERY_VERBOSE_DEBUG_LEVEL = 1;
+ # VERBOSE_DEBUG_LEVEL = 2;
+ # INFO_DEBUG_LEVEL = 3;
+ # WARN_DEBUG_LEVEL = 4;
+ # GRAVE_DEBUG_LEVEL = 5;
+
+ AC_ARG_WITH(minimal_debug_level,
+ AS_HELP_STRING([--with-minimal-debug-level=[grave|warn|info|verb|vverb]],
+ [set the MINIMAL_DEBUG_LEVEL. Standard debug streams with level below
+ MINIMAL_DEBUG_LEVEL will collapse to doing nothing if output is
+ requested. (default=warn)]
+ )
+ )
+
+ MINIMAL_DEBUG_LEVEL=4
+
+ case "$with_minimal_debug_level" in
+ grave)
+ MINIMAL_DEBUG_LEVEL=5
+ ;;
+ warn)
+ MINIMAL_DEBUG_LEVEL=4
+ ;;
+ info)
+ MINIMAL_DEBUG_LEVEL=3
+ ;;
+ verb)
+ MINIMAL_DEBUG_LEVEL=2
+ ;;
+ vverb)
+ MINIMAL_DEBUG_LEVEL=1
+ ;;
+ esac
+
+ AC_DEFINE_UNQUOTED([DUNE_MINIMAL_DEBUG_LEVEL], $MINIMAL_DEBUG_LEVEL,
+ [Standard debug streams with a level below will collapse to doing nothing])
+])
--- /dev/null
+## -*- autoconf -*-
+AC_DEFUN([DUNE_TR1_HEADERS], [
+ # Allow disabling tr1 headers. E.g. needed for broken xlc on Blue Gene
+ AC_LANG_PUSH([C++])
+ AC_ARG_ENABLE([tr1-headers],
+ [AS_HELP_STRING([--disable-tr1-headers],
+ [Prevents checking for tr1 headers like tuple, array, etc.
+ This might be needed for broken compilers like xlc on Blue Gene])],
+ [],
+ [enable_tr1_headers=yes])
+ AS_IF([test "x$enable_tr1_headers" != "xno"],
+ [AC_CHECK_HEADERS([type_traits tr1/type_traits tuple tr1/tuple])
+ AC_CACHE_CHECK([whether <array> C++0x is supported], dune_cv_array_cplusplus0x, [
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[#include <array>]],
+ [[std::array<int,2> a; a.fill(9);]])],
+ dune_cv_array_cplusplus0x=yes,
+ dune_cv_array_cplusplus0x=no)
+ ])
+ AS_IF([test "x$dune_cv_array_cplusplus0x" != "xno"],
+ [AC_DEFINE([HAVE_ARRAY], 1, [Define to 1 if the <array> C++0x is available and support array::fill])
+ ])
+ AC_CACHE_CHECK([whether integral_constant conforming to C++11 is supported], dune_cv_integral_constant_cplusplus11, [
+ AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([
+ #include <type_traits>
+ void f( int );
+ ],[
+ f( std::integral_constant< int, 42 >() );
+ ])
+ ],[
+ dune_cv_integral_constant_cplusplus11=yes
+ ],[
+ dune_cv_integral_constant_cplusplus11=no
+ ])
+ ])
+ AS_IF([test "x$dune_cv_integral_constant_cplusplus11" != "xno"],[
+ AC_DEFINE([HAVE_INTEGRAL_CONSTANT], 1, [Define to 1 if std::integral_constant< T, v > is supported and casts into T])
+ ])
+ AC_CACHE_CHECK([whether std::hash from C++11 is supported], dune_cv_hash_cplusplus11, [
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[#include <functional>]],
+ [[std::hash<int> hasher; hasher(42);]])],
+ dune_cv_hash_cplusplus11=yes,
+ dune_cv_hash_cplusplus11=no)
+ ])
+ AS_IF([test "x$dune_cv_hash_cplusplus11" != "xno"],
+ [AC_DEFINE([HAVE_STD_HASH], 1, [Define to 1 if the std::hash template from C++11 is available])
+ ])
+ AC_CACHE_CHECK([whether std::tr1::hash from TR1 is supported], dune_cv_hash_cplusplustr1, [
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[#include <tr1/functional>]],
+ [[std::tr1::hash<int> hasher; hasher(42);]])],
+ dune_cv_hash_cplusplustr1=yes,
+ dune_cv_hash_cplusplustr1=no)
+ ])
+ AS_IF([test "x$dune_cv_hash_cplusplustr1" != "xno"],
+ [AC_DEFINE([HAVE_TR1_HASH], 1, [Define to 1 if the std::tr1::hash template from TR1 is available])
+ ])
+ ])
+ AC_LANG_POP([C++])
+])
--- /dev/null
+# Check if __attribute__((unused)) is supported
+
+AC_DEFUN([DUNE_CHECKUNUSED],[
+ AC_CACHE_CHECK([for __attribute__((unused))], dune_cv_attribute_unused, [
+ AC_LANG_PUSH([C++])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #define UNUSED __attribute__((unused))
+ void f(int a UNUSED, int UNUSED)
+ {
+ int UNUSED b;
+ }
+ ]],
+ [])],
+ dune_cv_attribute_unused="yes",
+ dune_cv_attribute_unused="no")
+ AC_LANG_POP([C++])
+ ])
+
+ AS_IF([test "x$dune_cv_attribute_unused" = "xyes"],
+ [AC_DEFINE_UNQUOTED(HAS_ATTRIBUTE_UNUSED,
+ 1,
+ [does the compiler support __attribute__((unused))?])],)
+
+ AH_BOTTOM([#include <dune/common/unused.hh>])
+])
--- /dev/null
+# overwrite an internal function of autoconf
+#
+# The function below caused configure to abort if no fortran was available.
+# Changed it to just report a warning that we cannot compile
+# fortran programms.
+
+# __AC_FC_NAME_MANGLING
+# ---------------------
+# Test for the name mangling scheme used by the Fortran compiler.
+#
+# Sets ac_cv_{f77,fc}_mangling. The value contains three fields, separated
+# by commas:
+#
+# lower case / upper case:
+# case translation of the Fortran symbols
+# underscore / no underscore:
+# whether the compiler appends "_" to symbol names
+# extra underscore / no extra underscore:
+# whether the compiler appends an extra "_" to symbol names already
+# containing at least one underscore
+#
+AC_DEFUN([__AC_FC_NAME_MANGLING],
+[_AC_FORTRAN_ASSERT()dnl
+AC_CACHE_CHECK([for Fortran name-mangling scheme],
+ ac_cv_[]_AC_LANG_ABBREV[]_mangling,
+[AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+[ subroutine foobar()
+ return
+ end
+ subroutine foo_bar()
+ return
+ end])],
+[mv conftest.$ac_objext cfortran_test.$ac_objext
+
+ ac_save_LIBS=$LIBS
+ LIBS="cfortran_test.$ac_objext $LIBS $[]_AC_LANG_PREFIX[]LIBS"
+
+ AC_LANG_PUSH(C)dnl
+ ac_success=no
+ for ac_foobar in foobar FOOBAR; do
+ for ac_underscore in "" "_"; do
+ ac_func="$ac_foobar$ac_underscore"
+ AC_LINK_IFELSE([AC_LANG_CALL([], [$ac_func])],
+ [ac_success=yes; break 2])
+ done
+ done
+ AC_LANG_POP(C)dnl
+
+ if test "$ac_success" = "yes"; then
+ case $ac_foobar in
+ foobar)
+ ac_case=lower
+ ac_foo_bar=foo_bar
+ ;;
+ FOOBAR)
+ ac_case=upper
+ ac_foo_bar=FOO_BAR
+ ;;
+ esac
+
+ AC_LANG_PUSH(C)dnl
+ ac_success_extra=no
+ for ac_extra in "" "_"; do
+ ac_func="$ac_foo_bar$ac_underscore$ac_extra"
+ AC_LINK_IFELSE([AC_LANG_CALL([], [$ac_func])],
+ [ac_success_extra=yes; break])
+ done
+ AC_LANG_POP(C)dnl
+
+ if test "$ac_success_extra" = "yes"; then
+ ac_cv_[]_AC_LANG_ABBREV[]_mangling="$ac_case case"
+ if test -z "$ac_underscore"; then
+ ac_cv_[]_AC_LANG_ABBREV[]_mangling="$ac_cv_[]_AC_LANG_ABBREV[]_mangling, no underscore"
+ else
+ ac_cv_[]_AC_LANG_ABBREV[]_mangling="$ac_cv_[]_AC_LANG_ABBREV[]_mangling, underscore"
+ fi
+ if test -z "$ac_extra"; then
+ ac_cv_[]_AC_LANG_ABBREV[]_mangling="$ac_cv_[]_AC_LANG_ABBREV[]_mangling, no extra underscore"
+ else
+ ac_cv_[]_AC_LANG_ABBREV[]_mangling="$ac_cv_[]_AC_LANG_ABBREV[]_mangling, extra underscore"
+ fi
+ else
+ ac_cv_[]_AC_LANG_ABBREV[]_mangling="unknown"
+ fi
+ else
+ ac_cv_[]_AC_LANG_ABBREV[]_mangling="unknown"
+ fi
+
+ LIBS=$ac_save_LIBS
+ rm -f cfortran_test* conftest*],
+ [AC_MSG_WARN([cannot compile a simple Fortran program])])
+])
+])# __AC_FC_NAME_MANGLING
--- /dev/null
+## -*- autoconf -*-
+
+# DUNE_PATH_GMP()
+#
+# shell variables
+# with_gmp
+# no or path
+# HAVE_GMP
+# no or yes
+# GMP_CPPFLAGS
+# GMP_LIBS
+#
+# substitutions
+# GMP_CPPFLAGS
+# GMP_LIBS
+#
+# defines:
+# HAVE_GMP
+#
+# conditionals:
+# GMP
+AC_DEFUN([DUNE_PATH_GMP],[
+ AC_REQUIRE([AC_PROG_CXX])
+
+ AC_ARG_WITH([gmp],
+ [AS_HELP_STRING([--with-gmp=PATH],
+ [directory to GMP (GNU MP Bignum Library)])])
+
+ HAVE_GMP=no
+ AS_IF([test x"$with_gmp" = x"no"], [
+ AC_MSG_NOTICE([skipping check for GMP])
+ ], [
+ AC_CACHE_CHECK([for GMP], dune_cv_gmp_path, [
+ dune_cv_gmp_path=no
+ AS_IF([test x"$with_gmp" = x || test x"$with_gmp" = xyes], [
+ for d in /usr /usr/local; do
+ AC_MSG_NOTICE([searching for GMP in $d...])
+ DUNE_CHECK_PATH_GMP($d)
+ AS_IF([test $HAVE_GMP = yes],[
+ dune_cv_gmp_path=$d
+ break
+ ])
+ done],[
+ DUNE_CHECK_PATH_GMP($with_gmp)
+ AS_IF([test $HAVE_GMP = yes],[
+ dune_cv_gmp_path=$with_gmp
+ ])
+ ])
+ ])
+
+ if test "x$dune_cv_gmp_path" != xno; then
+ HAVE_GMP=yes
+ GMP_CPPFLAGS="-I$dune_cv_gmp_path/include -DENABLE_GMP=1"
+ GMP_LIBS="-L$dune_cv_gmp_path/lib -lgmpxx -lgmp"
+ fi
+ ])
+
+ AS_IF([test $HAVE_GMP = yes],[
+ AC_DEFINE([HAVE_GMP],[ENABLE_GMP],[Was GMP found and GMP_CPPFLAGS used?])
+ DUNE_ADD_ALL_PKG([GMP], [\${GMP_CPPFLAGS}],
+ [], [\${GMP_LIBS}])
+ ], [
+ GMP_CPPFLAGS=
+ GMP_LIBS=
+ ])
+
+ AC_SUBST([GMP_CPPFLAGS])
+ AC_SUBST([GMP_LIBS])
+
+ AM_CONDITIONAL(GMP,[test $HAVE_GMP = yes])
+ DUNE_ADD_SUMMARY_ENTRY([GMP],[$HAVE_GMP])
+])
+
+AC_DEFUN([DUNE_CHECK_PATH_GMP],[
+ GMP_CPPFLAGS="-I$1/include -DENABLE_GMP=1"
+ GMP_LIBS="-L$1/lib -lgmpxx -lgmp"
+
+ AC_LANG_PUSH([C++])
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ ac_save_LIBS="$LIBS"
+
+ CPPFLAGS="$CPPFLAGS $GMP_CPPFLAGS"
+
+ AC_CHECK_HEADER([gmpxx.h], [HAVE_GMP=yes],
+ [AC_MSG_WARN([gmpxx.h not found in $1])])
+
+ AS_IF([test $HAVE_GMP = yes],[
+ DUNE_CHECK_LIB_EXT([$1/lib], gmp,[__gmpz_abs],[],[
+ HAVE_GMP=no
+ AC_MSG_WARN(libgmp not found)])
+ ])
+
+ AS_IF([test $HAVE_GMP = yes],[
+ DUNE_CHECK_LIB_EXT([$1/lib], gmpxx,[__gmpz_abs],[],[
+ HAVE_GMP=no
+ AC_MSG_WARN(libgmpxx not found)])
+ ])
+
+ CPPFLAGS="$ac_save_CPPFLAGS"
+ LIBS="$ac_save_LIBS"
+ AC_LANG_POP([C++])
+])
+
--- /dev/null
+## -*- autoconf -*-
+# $Id$
+# searches for HDF5-stuff
+
+# DUNE_PATH_HDF5()
+#
+# shell variables:
+# with_hdf5
+# no, yes, or "yes (parallel)"
+# with_hdf5_libs
+# empty or something apropriate for LIBS
+# HDF5_CPPFLAGS
+# HDF5_LDFLAGS
+# HDF5_LIBS
+# direct_HDF5_CPPFLAGS
+# direct_HDF5_LDFLAGS
+# direct_HDF5_LIBS
+# same as above, but without variable indirections (e.g. the contents of
+# DUNEMPICPPFLAGS instead of '${DUNEMPICPPFLAGS}')
+# HDF5_PARALLEL
+# 1 or undef
+# HAVE_HDF5
+# 0 or 1
+#
+# substitutions:
+# HDF5_CPPFLAGS
+# HDF5_LDFLAGS
+# HDF5_LIBS
+#
+# defines:
+# HAVE_HDF5
+#
+# conditionals:
+# HDF5
+AC_DEFUN([DUNE_PATH_HDF5],[
+ AC_REQUIRE([AC_PROG_CC])
+ AC_REQUIRE([AC_PATH_XTRA])
+ AC_REQUIRE([DUNE_MPI])
+
+ AC_ARG_WITH(hdf5,
+ AC_HELP_STRING([--with-hdf5=PATH],[directory with HDF5 inside]),
+ # expand tilde / other stuff
+ eval with_hdf5=$with_hdf5
+ )
+
+ AC_ARG_WITH(hdf5_libs,
+ [AC_HELP_STRING([--with-hdf5-libs=LIBS],[additional libraries needed to link hdf5 programs. Those might be needed if your hdf5 library is static. Possible values are: -lz or -lz -lsz.])],[])
+
+ # store values
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ ac_save_LDFLAGS="$LDFLAGS"
+ ac_save_LIBS="$LIBS"
+
+ # start building variables
+
+ # use special HDF5-lib-path if it's set
+ if test x$with_hdf5 != x ; then
+ # extract absolute path
+ if test -d $with_hdf5; then
+ eval with_hdf5=`cd $with_hdf5 ; pwd`
+ else
+ AC_MSG_ERROR([HDF5-directory $with_hdf5 does not exist])
+ fi
+ _dune_hdf5_libpath="-L$with_hdf5/lib"
+ _dune_hdf5_incpath="-I$with_hdf5/include"
+ else
+ _dune_hdf5_libpath=""
+ _dune_hdf5_incpath=""
+ fi
+
+ CPPFLAGS="$CPPFLAGS $_dune_hdf5_incpath"
+
+ direct_HDF5_CPPFLAGS="$_dune_hdf5_incpath"
+ nodep_HDF5_CPPFLAGS="$_dune_hdf5_incpath"
+ HDF5_CPPFLAGS="$_dune_hdf5_incpath"
+ direct_HDF5_LDFLAGS=""
+ nodep_HDF5_LDFLAGS=""
+ HDF5_LDFLAGS=""
+ direct_HDF5_LIBS=""
+ nodep_HDF5_LIBS=""
+ HDF5_LIBS=""
+ HDF5_PARALLEL=0
+ # test if we are parallel
+ AC_CHECK_DECL(H5_HAVE_PARALLEL, [dnl
+ CPPFLAGS="$CPPFLAGS $DUNEMPICPPFLAGS"
+ direct_HDF5_CPPFLAGS="$HDF5_CPPFLAGS $DUNEMPICPPFLAGS"
+ HDF5_CPPFLAGS="$HDF5_CPPFLAGS \${DUNEMPICPPFLAGS}"
+ LDFLAGS="$LDFLAGS $DUNEMPILDFLAGS"
+ direct_HDF5_LDFLAGS="$HDF5_LDFLAGS $DUNEMPILDFLAGS"
+ HDF5_LDFLAGS="$HDF5_LDFLAGS \${DUNEMPILDFLAGS}"
+ LIBS="$DUNEMPILIBS $LIBS"
+ direct_HDF5_LIBS="$DUNEMPILIBS $HDF5_LIBS"
+ HDF5_LIBS="\${DUNEMPILIBS} $HDF5_LIBS"
+ HDF5_PARALLEL=1],[],[#include"H5pubconf.h"])
+
+ # test for an arbitrary header
+ AC_CHECK_HEADER([hdf5.h],
+ [HAVE_HDF5=1],
+ [HAVE_HDF5=0])
+
+ # Just for the configure check. In the end, -L has to go into LIBS.
+ LDFLAGS="$LDFLAGS $_dune_hdf5_libpath"
+ # test for lib
+ if test x$HAVE_HDF5 = x1 ; then
+ AC_CHECK_LIB([hdf5], [H5open],
+ [
+ direct_HDF5_LIBS="$_dune_hdf5_libpath -lhdf5 $with_hdf5_libs $direct_HDF5_LIBS"
+ nodep_HDF5_LIBS="$_dune_hdf5_libpath -lhdf5 $with_hdf5_libs $nodep_HDF5_LIBS"
+ HDF5_LIBS="$_dune_hdf5_libpath -lhdf5 $with_hdf5_libs $HDF5_LIBS"
+ ],
+ [HAVE_HDF5=0], ["$with_hdf5_libs"])
+ fi
+
+ # pre-set variable for summary
+ with_hdf5="no"
+
+ # did we succeed?
+ if test x$HAVE_HDF5 = x1 ; then
+ AC_DEFINE(HAVE_HDF5, 1, [Define to 1 if hdf5 was found])
+
+ # proudly show in summary
+ with_hdf5="yes"
+ if test x"$HDF5_PARALLEL" = x1; then
+ with_hdf5="$with_hdf5 (parallel)"
+ fi
+ else
+ # clear variables
+ direct_HDF5_CPPFLAGS=
+ nodep_HDF5_CPPFLAGS=
+ HDF5_CPPFLAGS=
+ direct_HDF5_LDFLAGS=
+ nodep_HDF5_LDFLAGS=
+ HDF5_LDFLAGS=
+ direct_HDF5_LIBS=
+ nodep_HDF5_LIBS=
+ HDF5_LIBS=
+ HDF5_PARALLEL=0
+ fi
+
+ AC_SUBST([HDF5_CPPFLAGS])
+ AC_SUBST([HDF5_LDFLAGS])
+ AC_SUBST([HDF5_LIBS])
+
+ # also tell automake
+ AM_CONDITIONAL(HDF5, test x$HAVE_HDF5 = x1)
+
+ # add to global list
+ DUNE_ADD_ALL_PKG([HDF5], [$nodep_HDF5_CPPFLAGS],
+ [$nodep_HDF5_LDFLAGS], [$nodep_HDF5_LIBS])
+
+ # reset values
+ LIBS="$ac_save_LIBS"
+ LDFLAGS="$ac_save_LDFLAGS"
+ CPPFLAGS="$ac_save_CPPFLAGS"
+
+ DUNE_ADD_SUMMARY_ENTRY([HDF5],[$with_hdf5])
+
+])
--- /dev/null
+dnl @synopsis IMMDX_LIB_METIS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl
+dnl This macro searches for the METIS library in the user specified
+dnl location. The user may specify the location either by defining the
+dnl environment variable METIS or by using the --with-metis option to
+dnl configure. If the environment variable is defined it has precedent
+dnl over everything else. If no location was specified then it searches
+dnl in /usr/lib and /usr/local/lib for the library and in /usr/include
+dnl and /usr/local/include for the header files. Upon sucessful
+dnl completion the variables METIS_LIB and METIS_INCLUDE are set.
+dnl
+dnl ACTION-IF-FOUND is a list of shell commands to run if a METIS
+dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to
+dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the
+dnl default action will define HAVE_METIS. If ACTION-IF-NOT-FOUND is
+dnl not specified then an error will be generated halting configure.
+dnl
+dnl @category InstalledPackages
+dnl @author Ben Bergen <ben@cs.fau.de>
+dnl @version 2003-01-19
+dnl @license AllPermissive
+
+AC_DEFUN([IMMDX_LIB_METIS], [
+ AC_MSG_CHECKING(for METIS library)
+ AC_REQUIRE([AC_PROG_CC])
+ #
+ # User hints...
+ #
+ AC_ARG_VAR([METIS], [METIS library location])
+ AC_ARG_WITH([metis],
+ [AC_HELP_STRING([--with-metis],
+ [user defined path to METIS library])],
+ [
+ if test -n "$METIS" ; then
+ AC_MSG_RESULT(yes)
+ with_metis=$METIS
+ elif test "$withval" != no ; then
+ AC_MSG_RESULT(yes)
+ with_metis=$withval
+ else
+ AC_MSG_RESULT(no)
+ fi
+ ],
+ [
+ if test -n "$METIS" ; then
+ with_metis=$METIS
+ AC_MSG_RESULT(yes)
+ else
+ with_metis=/usr
+ if test ! -f "$with_metis/include/metis.h" ; then
+ if test ! -f "$with_metis/include/metis/metis.h" ; then
+ with_metis=/usr/local
+ if test ! -f "$with_metis/include/metis.h" ; then
+ with_metis=""
+ AC_MSG_RESULT(failed)
+ else
+ AC_MSG_RESULT(yes)
+ fi
+ fi
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(yes)
+ fi
+ fi
+ ])
+ #
+ # locate METIS library
+ #
+ if test -n "$with_metis" ; then
+ old_CFLAGS=$CFLAGS
+ old_LDFLAGS=$LDFLAGS
+
+ if test -f "$with_metis/include/metis.h"; then
+ lib_path="/lib"
+ include_path="/include"
+ fi
+
+ if test -f "$with_metis/include/metis/metis.h"; then
+ lib_path="/lib"
+ include_path="/include/metis"
+ fi
+
+ if test -f "$with_metis/Lib/metis.h"; then
+ # catch bad convention in the downloadable metis version
+ lib_path=""
+ include_path="/Lib"
+ fi
+ CFLAGS="-I$with_metis/$include_path"
+ LDFLAGS="-L$with_metis/$lib_path"
+
+ AC_LANG_SAVE
+ AC_LANG_C
+
+ AC_CHECK_LIB(metis, METIS_PartGraphKway,
+ [metis_lib=yes], [metis_lib=no], [-lm])
+
+
+ AC_CHECK_HEADER(metis.h, [metis_h=yes],
+ [metis_h=no], [/* check */])
+ #echo x$metis_h
+
+ AC_LANG_RESTORE
+
+ CFLAGS=$old_CFLAGS
+ LDFLAGS=$old_LDFLAGS
+
+ AC_MSG_CHECKING(METIS in $with_metis)
+ if test "$metis_lib" = "yes" -a "$metis_h" = "yes" ; then
+ AC_SUBST(METIS_INCLUDE, [-I$with_metis$include_path])
+ AC_SUBST(METIS_LDFLAGS, [-L$with_metis$lib_path])
+ AC_SUBST(METIS_LIB, [-lmetis])
+ AC_MSG_RESULT(ok)
+ else
+ AC_MSG_RESULT(failed)
+ fi
+ fi
+ #
+ #
+ #
+
+ # tell automake
+ AM_CONDITIONAL(METIS, test x$METIS_LIB = x1)
+ if test x = x"$METIS_LIB" ; then
+ with_metis=no
+ ifelse([$2],,[AC_MSG_WARN(Failed to find valid METIS library)],[$2])
+ :
+ else
+ with_metis=yes
+ ifelse([$1],,[AC_DEFINE(HAVE_METIS,1,[Define if you have METIS library])
+ ],[$1])
+ :
+ fi
+ DUNE_ADD_SUMMARY_ENTRY([METIS],[$with_metis])
+ ])dnl IMMDX_LIB_METIS
--- /dev/null
+# $Id$
+
+# Check for inkscape and define automake conditional
+
+AC_DEFUN([DUNE_INKSCAPE],[
+ AC_CHECK_PROG([INKSCAPE], [inkscape], [inkscape], [no])
+ AC_ARG_VAR([INKSCAPE], [path to inkscape to regenerate .png's from .svg's.])
+ AM_CONDITIONAL([INKSCAPE], [test "x$INKSCAPE" != xfalse && test "x$INKSCAPE" != xno])
+])
--- /dev/null
+dnl Compatibility m4 to make dune work with
+dnl libtool 1.5 and libtool 2.x
+
+AC_DEFUN([LT_COMPAT],[
+ # LT_COMPAT
+ m4_ifdef([LT_OUTPUT],[],[AC_DEFUN([LT_OUTPUT])])
+])
--- /dev/null
+AC_DEFUN([MAKE_SHARED],[
+ AC_REQUIRE([SHARED_PTR])
+ AS_IF([test "$SHARED_PTR_NAMESPACE" = "boost"],[
+ AC_CHECK_HEADER([boost/make_shared.hpp],
+ [AC_DEFINE([HAVE_BOOST_MAKE_SHARED_HPP], [1],
+ [Define to 1 if you have <boost/make_shared.hpp>.])
+ ])
+ ])
+ AC_CACHE_CHECK([whether SHARED_PTR_NAMESPACE ($SHARED_PTR_NAMESPACE) provides make_shared],
+ dune_cv_make_shared, [
+ AC_LANG_PUSH([C++])
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[
+#if defined(HAVE_MEMORY)
+# include <memory>
+#endif
+#if defined(HAVE_TR1_MEMORY)
+# include <tr1/memory>
+#endif
+#if defined(HAVE_BOOST_SHARED_PTR_HPP) && defined(HAVE_BOOST_MAKE_SHARED_HPP)
+# include <boost/shared_ptr.hpp>
+# include <boost/make_shared.hpp>
+#endif
+#include <string>
+ ]],[[
+$SHARED_PTR_NAMESPACE::make_shared<int>(3);
+ ]])],
+ dune_cv_make_shared=yes,
+ dune_cv_make_shared=no)
+ AC_LANG_POP
+ ])
+ AS_IF([test "$dune_cv_make_shared" = "yes"],[
+ AC_DEFINE([HAVE_MAKE_SHARED], [1],
+ [Define to 1 if SHARED_PTR_NAMESPACE::make_shared is usable.])])
+])
--- /dev/null
+AC_DEFUN([MPI_CONFIG_HELPER],[
+
+mpi_trybuild () {
+ $MPICC ${1} > /dev/null 2>&1 || return 1
+ return 0
+}
+
+mpi_trybuild_run () {
+ mpi_trybuild "-o conftest ${1}" || return 1
+ ./conftest 2>&1 || return 1
+ return 0
+}
+
+mpi_preprocess () {
+ $MPICC -E -c ${1} 2> /dev/null
+}
+
+mpi_getflags () {
+ # -- call mpiCC, remove compiler name
+ # compiler-name is first word in line _if_ it doesn't start with a dash!
+ # needed because mpiCC sometimes does not include compiler (newer LAM)
+
+ # the additional brackets keep m4 from interpreting the brackets
+ # in the sed-command...
+ retval=`$MPICC ${1} ${2} 2>/dev/null | head -1`
+ # remove compiler name
+ retval=`echo $retval | sed -e 's/^[[^-]][[^ ]][[^ ]]* //'`
+ # remove dummy-parameter (if existing)
+ retval=`echo $retval | sed -e "s/ ${1} / /"`
+ if test ${#} = 2 ; then
+ retval=`echo $retval | sed -e "s/ ${2} / /"`
+ fi
+ # remove optimization, warning, etc paramters
+ retval=`echo " $retval " | sed -e 's/ -g / /g' -e 's/ -W[[a-z0-9]]\+ / /g' -e 's/ -O[[0-9]]\+ / /g'`
+ # strip leading and trailing spaces
+ retval=`echo "$retval" | sed 's/^ *//g;s/ *$//g'`
+}
+
+# removes regexp $2 from string $1
+mpi_remove () {
+ retval=`echo ${1} | sed -e "s/ ${2} / /"`
+ # string to remove might be on the beginning of the line
+ retval=`echo ${retval} | sed -e "s/^${2} / /"`
+}
+
+test_lam () {
+ AC_MSG_CHECKING([for lam])
+ cat >conftest.c <<_EOF
+#include <mpi.h>
+#include <stdio.h>
+
+int main() {
+ printf ("%i%i\n", LAM_MAJOR_VERSION, LAM_MINOR_VERSION);
+ return 0;
+ }
+_EOF
+
+ if mpi_trybuild "-c conftest.c"; then
+ # try new -showme:xxx function
+ mpi_getflags "-showme:compile"
+ if test x"$retval" != x ; then
+ # seems like LAM >= 7.1 which supports extraction of parameters without
+ # dummy files
+ dune_MPI_VERSION="LAM >= 7.1"
+ if test x"$DUNEMPICPPFLAGS" = x; then
+ DUNEMPICPPFLAGS="$retval"
+ fi
+ if test x"$DUNEMPILIBS" = x; then
+ mpi_getflags "-showme:link"
+ DUNEMPILIBS="$retval"
+ fi
+ else
+ dune_MPI_VERSION="LAM < 7.1"
+ # use -showme and dummy parameters to extract flags
+ if test x"$DUNEMPICPPFLAGS" = x; then
+ mpi_getflags "-showme" "-c $MPISOURCE"
+ DUNEMPICPPFLAGS="$retval"
+ fi
+ if test x"$DUNEMPILIBS" = x; then
+ mpi_getflags "-showme" "dummy.o -o dummy"
+ DUNEMPILIBS="$retval"
+ fi
+ fi
+ # hack in option to disable LAM-C++-bindings...
+ # we fake to have mpicxx.h read already
+ MPI_NOCXXFLAGS="-DMPIPP_H"
+ AC_MSG_RESULT([yes])
+ rm -f conftest*
+ return 0
+ fi
+
+ rm -f conftest*
+ AC_MSG_RESULT([no])
+ return 1
+}
+
+mpi_getmpichflags() {
+ if test x"$DUNEMPICPPFLAGS" = x; then
+ # use special commands to extract options
+ mpi_getflags "-compile_info"
+ DUNEMPICPPFLAGS="$retval"
+ # remove implicitly set -c
+ mpi_remove "$DUNEMPICPPFLAGS" '-c'
+ DUNEMPICPPFLAGS="$retval"
+ fi
+
+ if test x"$DUNEMPILIBS" = x; then
+ # get linker options
+ mpi_getflags "-link_info"
+ DUNEMPILIBS="$retval"
+ # strip -o option
+ mpi_remove "$DUNEMPILIBS" "-o"
+ DUNEMPILIBS="$retval"
+ #strip DUNEMPICPPFLAGS (which are included for mpich2 on jugene)
+ enc=`echo "$DUNEMPICPPFLAGS" | sed -e 's/\\//\\\\\\//g'`
+ DUNEMPILIBS=`echo "$retval" | sed -e "s/$enc / /"`
+ fi
+
+ # hack in option to disable MPICH-C++-bindings...
+ MPI_NOCXXFLAGS="-DMPICH_SKIP_MPICXX"
+}
+
+mpi_getmpich2flags() {
+ if test x"$DUNEMPICPPFLAGS" = x; then
+ # use special commands to extract options
+ mpi_getflags "-show" "-c"
+ DUNEMPICPPFLAGS="$retval"
+ # remove implicitly set -c
+ mpi_remove "$DUNEMPICPPFLAGS" '-c'
+ DUNEMPICPPFLAGS="$retval"
+ fi
+
+ if test x"$DUNEMPILIBS" = x; then
+ # get linker options
+ mpi_getflags "-show" "-o"
+ DUNEMPILIBS="$retval"
+ # strip -o option
+ mpi_remove "$DUNEMPILIBS" "-o"
+ DUNEMPILIBS="$retval"
+ #strip DUNEMPICPPFLAGS (which are included for mpich2 on jugene)
+ enc=`echo "$DUNEMPICPPFLAGS" | sed -e 's/\\//\\\\\\//g'`
+ DUNEMPILIBS=`echo "$retval" | sed -e "s/$enc / /"`
+ fi
+
+ # hack in option to disable MPICH-C++-bindings...
+ MPI_NOCXXFLAGS="-DMPICH_SKIP_MPICXX"
+}
+
+test_mpich () {
+ AC_MSG_CHECKING([for mpich])
+ cat >conftest.c <<_EOF
+#include <mpi.h>
+
+int main() { return 0; }
+_EOF
+
+ if (mpi_preprocess conftest.c \
+ | grep -q MPICHX_PARALLELSOCKETS_PARAMETERS); then
+ dune_MPI_VERSION="MPICH"
+ mpi_getmpichflags
+
+ AC_MSG_RESULT([yes])
+ rm -f conftest*
+ return 0
+ fi
+
+ rm -f conftest*
+ AC_MSG_RESULT([no])
+ return 1
+}
+
+test_mpich2 () {
+ AC_MSG_CHECKING([for mpich2])
+ cat >conftest.c <<_EOF
+#include <mpi.h>
+#include <stdio.h>
+int main() { printf ("%s\n", MPICH2_VERSION); return 0; }
+_EOF
+
+ if mpi_trybuild "-c conftest.c"; then
+ dune_MPI_VERSION="MPICH2"
+ mpi_getmpich2flags
+
+ AC_MSG_RESULT([yes])
+ rm -f conftest*
+ return 0
+ fi
+
+ rm -f conftest*
+ AC_MSG_RESULT([no])
+ return 1
+}
+
+test_mpich3 () {
+ AC_MSG_CHECKING([for mpich 3.x])
+ cat >conftest.c <<_EOF
+#include <mpi.h>
+#include <stdio.h>
+int main() { printf ("%s\n", MPICH_VERSION); return 0; }
+_EOF
+
+ if (mpi_trybuild_run "conftest.c" | grep -q "^3\.") ; then
+ dune_MPI_VERSION="MPICH2"
+ mpi_getmpich2flags
+
+ AC_MSG_RESULT([yes])
+ rm -f conftest*
+ return 0
+ fi
+
+ rm -f conftest*
+ AC_MSG_RESULT([no])
+ return 1
+}
+
+test_openmpi () {
+ AC_MSG_CHECKING([for OpenMPI])
+ cat >conftest.c <<_EOF
+#include <mpi.h>
+
+int main() { return 0; }
+_EOF
+
+ if (mpi_preprocess conftest.c | grep -q ompi_communicator_t); then
+ dune_MPI_VERSION="OpenMPI"
+
+ if test x"$DUNEMPICPPFLAGS" = x; then
+ mpi_getflags "-showme:compile"
+ DUNEMPICPPFLAGS="$retval"
+ fi
+ if test x"$DUNEMPILIBS" = x; then
+ mpi_getflags "-showme:link"
+ DUNEMPILIBS="$retval"
+ fi
+ MPI_NOCXXFLAGS="-DMPIPP_H"
+
+ AC_MSG_RESULT([yes])
+ rm -f conftest*
+ return 0
+ fi
+
+ rm -f conftest*
+ AC_MSG_RESULT([no])
+ return 1
+}
+
+test_mvapich() {
+ AC_MSG_CHECKING([for MVAPICH])
+
+ mpi_getflags "-v" "-c dummy.c"
+ if (echo $dune_MPI_VERSION | grep ^MVAPICH>/dev/null);then
+ get_mpichflags
+
+ AC_MSG_RESULT([yes])
+ return 0
+ fi
+
+ AC_MSG_RESULT([no])
+ return 1
+}
+
+test_mvapich2() {
+ AC_MSG_CHECKING([for MVAPICH2])
+ cat >conftest.c <<_EOF
+#define _OSU_MVAPICH_
+#include <mpi.h>
+/* MVAPICH2_VERSION is only defined for MVAPICH2 1.4+
+ * MVAPICH_VERSION is only defined for MVAPICH2 1.2.*
+ * We can thus fall back to MVAPICH_VERSION if MVAPICH2_VERSION
+ * is not defined.
+ */
+#ifndef MVAPICH2_VERSION
+#define MVAPICH2_VERSION MVAPICH_VERSION
+#endif
+#include <stdio.h>
+int main() { printf("%s\n",MVAPICH2_VERSION); return 0; }
+_EOF
+
+ if mpi_trybuild "-c conftest.c"; then
+ dune_MPI_VERSION="MVAPICH2"
+ mpi_getmpich2flags
+
+ AC_MSG_RESULT([yes])
+ rm -f conftest*
+ return 0
+ fi
+
+ rm -f conftest*
+ AC_MSG_RESULT([no])
+ return 1
+}
+
+test_ibmmpi() {
+ AC_MSG_CHECKING([for IBM MPI])
+ if $MPICC -v -c conftest.c > /dev/null 2>&1; then
+ mpi_getflags "-v" "-c dummy.c"
+ if (echo $retval | grep '^xl[[cC]]'); then
+ dune_MPI_VERSION="IBM MPI"
+
+ if test x"$DUNEMPICPPFLAGS" = x; then
+ DUNEMPICPPFLAGS="$retval"
+ fi
+
+ if test x"$DUNEMPILIBS" = x; then
+ mpi_getflags "-v" "dummy.o -o dummy"
+ DUNEMPILIBS="$retval"
+ fi
+
+ AC_MSG_RESULT([yes])
+ rm -f conftest*
+ return 0
+ fi
+ fi
+
+ AC_MSG_RESULT([no])
+ return 1
+}
+
+test_intelmpi() {
+ AC_MSG_CHECKING([for Intel MPI])
+ mpi_getflags "-v"
+ if (echo $retval | grep 'Intel(R) MPI Library'); then
+ dune_MPI_VERSION="Intel MPI"
+ mpi_getmpich2flags
+
+ AC_MSG_RESULT([yes])
+ return 0
+ fi
+
+ AC_MSG_RESULT([no])
+ return 1
+}
+
+get_mpiparameters() {
+ AC_MSG_NOTICE([Trying to identify the version of MPI compiler $MPICC])
+
+ if test x"$dune_MPI_VERSION" != x; then
+ return
+ fi
+
+ test_lam && return
+ test_mpich && return
+ test_openmpi && return
+ test_mvapich && return
+ test_mvapich2 && return
+ test_mpich2 && return
+ test_mpich3 && return
+ test_ibmmpi && return
+ test_intelmpi && return
+
+ dune_MPI_VERSION="unknown"
+ AC_MSG_ERROR([Could not identify MPI-package! Please send a bugreport and tell us what MPI-package you're using.])
+}
+])
+
+AC_DEFUN([MPI_CONFIG],[
+ AC_REQUIRE([MPI_CONFIG_HELPER])
+ get_mpiparameters;
+])
--- /dev/null
+dnl searches for the sys/mman.h header
+dnl and checks the mprotect is available
+
+AC_DEFUN([DUNE_SYS_MPROTECT],[
+ AC_REQUIRE([AC_PROG_CC])
+ AC_LANG_PUSH([C])
+ AC_CHECK_HEADER(sys/mman.h,
+ AC_DEFINE(HAVE_SYS_MMAN_H, 1,
+ [Define to 1 if you have <sys/mman.h>.])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <sys/mman.h>],[mprotect(0,0,PROT_NONE);])],
+ [AC_DEFINE(HAVE_MPROTECT, 1,
+ [Define to 1 if you have the symbol mprotect.])]))
+ AC_LANG_POP()
+])
--- /dev/null
+## -*- autoconf -*-
+# $Id$
+# searches for OpenGL-stuff
+
+# DUNE_PATH_OPENGL()
+#
+# Call AX_CHECK_OPENGL, but also add the discovered flags too the ALL_PKG_*
+# family and add a summary entry. Also make sure that pthreads are supported.
+AC_DEFUN([DUNE_PATH_OPENGL],[
+dnl use test from autoconf-archive
+ AC_REQUIRE([AX_CHECK_GL])
+
+ # GL_LIBS and GL_CFLAGS already set correctly, they implicitly
+ # contain pthread support!
+
+ # variable for summary
+ with_opengl="no"
+ if test "$no_gl" != "yes" ; then
+ with_opengl="yes (add GL_LIBS to LDADD manually, etc.)"
+
+ # need pthreads-stuff in linker commandline as well
+ AC_SUBST(GL_LDFLAGS, $PTHREAD_CFLAGS)
+ # GL_CFLAGS contain stuff like -pthread, which according to the gcc
+ # documentation is a flag for both the preprocessor and the linker. So we
+ # add it to the preprocessor flags here.
+ AC_SUBST(GL_LIBS, $GL_LIBS)
+ AC_SUBST(GL_LDFLAGS, $GL_LDFLAGS)
+ AC_SUBST(GL_CPPFLAGS, $GL_CFLAGS)
+ fi
+
+ DUNE_ADD_SUMMARY_ENTRY([OpenGL],[$with_opengl])
+])
--- /dev/null
+dnl -*- mode: autoconf; tab-width: 8; indent-tabs-mode: nil; -*-
+dnl vi: set et ts=8 sw=2 sts=2:
+# $Id$
+# searches for ParMetis headers and libs
+
+AC_DEFUN([DUNE_PATH_PARMETIS],[
+ AC_REQUIRE([AC_PROG_CC])
+ AC_REQUIRE([AC_PATH_XTRA])
+ AC_REQUIRE([DUNE_MPI])
+
+ # default locations
+ PARMETIS_DEFAULT="/usr /usr/local"
+ INCLUDE_DEFAULT="include include/parmetis"
+
+ #
+ # User hints ...
+ #
+ AC_ARG_VAR([PARMETIS], [ParMETIS library location])
+ AC_ARG_WITH([parmetis],
+ [AC_HELP_STRING([--with-parmetis],[user defined path to ParMETIS library])],
+ [
+ # --with-parmetis supersedes $PARMETIS
+ PARMETIS="$withval"
+ ])
+ # set PARMETIS to the usual locations, in case it is not defined
+ if test -n "$PARMETIS" ; then PARMETIS_DEFAULT=""; fi
+ with_parmetis=""
+ include_path=""
+ lib_path=""
+ # check for parmtirs include path
+ for p in "$PARMETIS" $PARMETIS_DEFAULT; do
+ for i in $INCLUDE_DEFAULT; do
+# AC_MSG_NOTICE( ... checking for $p/$i )
+ if test -f $p/$i/parmetis.h ; then
+# AC_MSG_NOTICE( ... found $p/$i/parmetis.h )
+ with_parmetis="$p"
+ include_path="$i"
+ lib_path=lib
+ break 2;
+ fi
+ done
+ done
+ # report test result
+ if test -n "$with_parmetis" ; then
+ # defaultpath
+ PARMETIS_LIB_PATH="$with_parmetis/$lib_path"
+ PARMETIS_INCLUDE_PATH="$with_parmetis/$include_path"
+
+ AC_MSG_RESULT(yes)
+ else
+ if test -n "$PARMETIS" && test "$PARMETIS" != "no" ; then
+ AC_MSG_ERROR(ParMETIS was part of the configure call but could not be found in $PARMETIS)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ fi
+
+ AC_MSG_NOTICE( PARMETIS: checking for $p/$i )
+ AC_ARG_WITH([parmetis-lib],
+ [AC_HELP_STRING([--with-parmetis-lib], [name of the parmetis libraries (default is parmetis)])],
+ ,[with_parmetis_lib=parmetis])
+ AC_ARG_WITH([metis-lib],
+ [AC_HELP_STRING([--with-metis-lib], [name of the metis libraries (default is metis)])],
+ ,[with_metis_lib=metis])
+
+ #echo with_parmetis=$with_parmetis
+ # store old values
+ ac_save_LDFLAGS="$LDFLAGS"
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ ac_save_LIBS="$LIBS"
+
+ # call IMDX_LIB_METIS directly and not via AC_REQUIRE
+ # because AC_REQUIRE support not allow parameters
+ # without any parameters a missing METIS would halt configure
+ IMMDX_LIB_METIS(,[true])
+
+ ## do nothing if --without-parmetis is used
+ if test x"$with_mpi" != x"no" && test x"$with_parmetis" != x"no" ; then
+
+ PARMETIS_LIBS="-L$PARMETIS_LIB_PATH -l$with_metis_lib $DUNEMPILIBS -lm"
+ PARMETIS_LDFLAGS="$DUNEMPILDFLAGS"
+
+ # set variables so that tests can use them
+ CPPFLAGS="$CPPFLAGS -I$PARMETIS_INCLUDE_PATH $METIS_INCLUDE $DUNEMPICPPFLAGS"
+
+ # check for central header
+ AC_CHECK_HEADER([parmetis.h],[
+ PARMETIS_CPPFLAGS="-I$PARMETIS_INCLUDE_PATH $METIS_INCLUDE"
+ HAVE_PARMETIS="1"],[
+ HAVE_PARMETIS="0"
+ AC_MSG_WARN([parmetis.h not found in $PARMETIS_INCLUDE_PATH with $CPPFLAGS])]
+ )
+
+ PARMETIS_CPPFLAGS="${DUNEMPICPPFLAGS} ${PARMETIS_CPPFLAGS} -DENABLE_PARMETIS=1"
+
+# AC_LANG_PUSH([C++])
+
+ # if header is found check for the libs
+
+ LIBS="$DUNEMPILIBS -lm $LIBS"
+
+ if test x$HAVE_PARMETIS = x1 ; then
+ DUNE_CHECK_LIB_EXT([$PARMETIS_LIB_PATH], [$with_metis_lib], [metis_partgraphkway],
+ [
+ PARMETIS_LIBS="-L$PARMETIS_LIB_PATH -l$with_metis_lib $METIS_LDFLAGS $DUNEMPILIBS -lm"
+ LIBS="$PARMETIS_LIBS $ac_save_LIBS"
+ ],[
+ HAVE_PARMETIS="0"
+ AC_MSG_WARN(libmetis not found!)
+ ])
+ fi
+
+ if test x$HAVE_PARMETIS = x1 ; then
+ DUNE_CHECK_LIB_EXT([$PARMETIS_LIB_PATH], [$with_parmetis_lib], [parmetis_v3_partkway],
+ [
+ PARMETIS_LIBS="-L$PARMETIS_LIB_PATH -l$with_parmetis_lib $PARMETIS_LIBS"
+ ],[
+ HAVE_PARMETIS="0"
+ AC_MSG_WARN(libparmetis not found!)
+ ])
+ fi
+
+# AC_LANG_POP([C++])
+
+ # pre-set variable for summary
+ #with_parmetis="no"
+
+ # did it work?
+ AC_MSG_CHECKING(ParMETIS in $with_parmetis)
+ if test x$HAVE_PARMETIS = x1 ; then
+ AC_SUBST(PARMETIS_LIBS, $PARMETIS_LIBS)
+ AC_SUBST(PARMETIS_LDFLAGS, $PARMETIS_LDFLAGS)
+ AC_SUBST(PARMETIS_CPPFLAGS, $PARMETIS_CPPFLAGS)
+ AC_DEFINE(HAVE_PARMETIS,ENABLE_PARMETIS,[Define if you have the Parmetis library.
+ This is only true if MPI was found by configure
+ _and_ if the application uses the PARMETIS_CPPFLAGS])
+ AC_MSG_RESULT(ok)
+
+ # add to global list
+ DUNE_ADD_ALL_PKG([PARMETIS], [\${PARMETIS_CPPFLAGS}],
+ [\${PARMETIS_LDFLAGS}], [\${PARMETIS_LIBS}])
+
+ # re-set variable correctly
+ with_parmetis="yes"
+ else
+ AC_SUBST(PARMETIS_LIBS, "")
+ AC_SUBST(PARMETIS_LDFLAGS, "")
+ AC_SUBST(PARMETIS_CPPFLAGS, "")
+ with_parmetis="no"
+ AC_MSG_RESULT(failed)
+ fi
+
+ # end of "no --without-parmetis"
+ else
+ with_parmetis="no"
+ fi
+
+ # tell automake
+ AM_CONDITIONAL(PARMETIS, test x$HAVE_PARMETIS = x1)
+
+ # restore variables
+ LDFLAGS="$ac_save_LDFLAGS"
+ CPPFLAGS="$ac_save_CPPFLAGS"
+ LIBS="$ac_save_LIBS"
+
+ DUNE_ADD_SUMMARY_ENTRY([ParMETIS],[$with_parmetis])
+
+])
--- /dev/null
+dnl Copyright (C) 2009 Sun Microsystems
+dnl This file is free software; Sun Microsystems
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl We check two things: where is the memory include file, and in what
+dnl namespace does shared_ptr reside.
+dnl We include AC_COMPILE_IFELSE for all the combinations we've seen in the
+dnl wild:
+dnl
+dnl GCC 4.3: namespace: std:: #include <memory>
+dnl GCC 4.2: namespace: tr1:: #include <tr1/memory>
+dnl GCC 4.2: namespace: boost:: #include <boost/shared_ptr.hpp>
+dnl
+dnl We define one of HAVE_HAVE_TR1_SHARED_PTR or HAVE_BOOST_SHARED_PTR
+dnl depending on location, SHARED_PTR_HEADER to be the header with enclosing
+dnl brackety braces in which shared_ptr is defined and SHARED_PTR_NAMESPACE to
+dnl be the namespace in
+dnl which shared_ptr is defined.
+dnl
+
+AC_DEFUN([SHARED_PTR],[
+dnl AC_REQUIRE([PANDORA_CHECK_CXX_STANDARD])
+ AC_REQUIRE([DUNE_TR1_HEADERS])
+ AC_LANG_PUSH(C++)
+ AS_IF([test "x$enable_tr1_headers" != "xno"],
+ [AC_CHECK_HEADERS([memory tr1/memory])])
+ AC_CHECK_HEADERS([boost/shared_ptr.hpp])
+ AC_CACHE_CHECK([the location of shared_ptr header file],
+ [ac_cv_shared_ptr_h],[
+ for namespace in std tr1 std::tr1 boost
+ do
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[
+#include <string>
+
+using $namespace::shared_ptr;
+using namespace std;
+ ]],[[
+shared_ptr<string> test_ptr(new string("test string"));
+ ]])],
+ [
+ ac_cv_shared_ptr_namespace="${namespace}"
+ ac_cv_shared_ptr_header=missing
+ break
+ ],[
+ ac_cv_shared_ptr_namespace=missing
+ ac_cv_shared_ptr_header=missing
+ ])
+ for header in memory tr1/memory boost/shared_ptr.hpp; do
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[
+# include <$header>
+#include <string>
+
+using $namespace::shared_ptr;
+using namespace std;
+ ]],[[
+shared_ptr<string> test_ptr(new string("test string"));
+ ]])],
+ [
+ ac_cv_shared_ptr_namespace="${namespace}"
+ ac_cv_shared_ptr_header="<${header}>"
+ break
+ ],[
+ ac_cv_shared_ptr_namespace=missing
+ ac_cv_shared_ptr_header=missing
+ ])
+ done
+ if test "$ac_cv_shared_ptr_namespace" != "missing"; then break; fi
+ done
+ ])
+ AS_IF([ test "x$ac_cv_shared_ptr_namespace" = xmissing ],
+ [], [
+ SHARED_PTR_NAMESPACE=${ac_cv_shared_ptr_namespace}
+ AC_DEFINE_UNQUOTED([SHARED_PTR_NAMESPACE],
+ ${ac_cv_shared_ptr_namespace},
+ [The namespace in which SHARED_PTR can be found])
+ ]
+ )
+ AS_IF([ test "x$ac_cv_shared_ptr_header" = xmissing ],
+ [], [
+ SHARED_PTR_HEADER=${ac_cv_shared_ptr_header}
+ AC_DEFINE_UNQUOTED([SHARED_PTR_HEADER],
+ ${ac_cv_shared_ptr_header},
+ [The header in which SHARED_PTR can be found])
+ ]
+ )
+ AC_LANG_POP()
+])
--- /dev/null
+# courtesy of the dune-fem maintainers
+
+AC_DEFUN([DUNE_PATH_UMFPACK],[
+ AC_REQUIRE([AC_PROG_CC])
+
+ AC_ARG_WITH(umfpack,
+ AC_HELP_STRING([--with-umfpack=PATH],[directory with UMFPACK inside]))
+ AC_ARG_WITH(umfpack-includedir,
+ AC_HELP_STRING([--with-umfpack-includedir=PATH],[directory with UMFPACK headers inside]))
+ AC_ARG_WITH(umfpack-libdir,
+ AC_HELP_STRING([--with-umfpack-libdir=PATH],[directory with UMFPACK libraries inside]))
+
+# store old values
+ac_save_LDFLAGS="$LDFLAGS"
+ac_save_CPPFLAGS="$CPPFLAGS"
+ac_save_LIBS="$LIBS"
+
+UMFPACKYES=0
+## do nothing if no --with-umfpack was supplied
+if test x$with_umfpack != x && test x$with_umfpack != xno ; then
+ UMFPACKYES=1
+fi
+if test x$with_umfpack_includedir != x && test x$with_umfpack_includedir != xno ; then
+ UMFPACKYES=1
+fi
+if test x$with_umfpack_libdir != x && test x$with_umfpack_libdir != xno ; then
+ UMFPACKYES=1
+fi
+
+if test x$UMFPACKYES = x1 ; then
+
+ # is --with-umfpack=bla used?
+ if test "x$with_umfpack" != x ; then
+ UMFPACKROOT=`cd $with_umfpack && pwd`
+ if ! test -d $UMFPACKROOT; then
+ AC_MSG_WARN([UMFPACK directory $with_umfpack does not exist])
+ fi
+
+ if test "x$UMFPACKROOT" = x; then
+ # use some default value...
+ UMFPACKROOT="/usr/local/umfpack"
+ fi
+
+ UMFAMD_LIB_PATH="$UMFPACKROOT/AMD/Lib"
+ UMFPACK_LIB_PATH="$UMFPACKROOT/UMFPACK/Lib"
+ UMFPACK_INCLUDE_PATH="$UMFPACKROOT/UMFPACK/Include"
+ else
+ if test "x$with_umfpack_includedir" != x ; then
+ UMFPACK_INCLUDE_PATH=`cd $with_umfpack_includedir && pwd`
+ if ! test -d $UMFPACK_INCLUDE_PATH; then
+ AC_MSG_WARN([UMFPACK directory $with_umfpack_includedir does not exist])
+ fi
+ fi
+ if test "x$with_umfpack_libdir" != x ; then
+ UMFPACK_LIB_PATH=`cd $with_umfpack_libdir && pwd`
+ if ! test -d $UMFPACK_LIB_PATH; then
+ AC_MSG_WARN([UMFPACK directory $with_umfpack_libdir does not exist])
+ fi
+ fi
+ UMFAMD_LIB_PATH=$UMFPACK_LIB_PATH
+ fi
+
+ # set variables so that tests can use them
+ REM_CPPFLAGS=$CPPFLAGS
+
+ LDFLAGS="$LDFLAGS -L$UMFPACK_LIB_PATH -L$UMFAMD_LIB_PATH"
+ UMFPACK_INC_FLAG="-I$UMFPACK_INCLUDE_PATH -I$UMFPACKROOT/UFconfig -I$UMFPACKROOT/AMD/Include -I$UMFPACKROOT/SuiteSparse_config -DENABLE_UMFPACK=1"
+ CPPFLAGS="$CPPFLAGS $UMFPACK_INC_FLAG $MPI_CPPFLAGS"
+
+ # check for header
+ AC_LANG_PUSH([C])
+ AC_CHECK_HEADERS([umfpack.h],
+ [UMFPACK_CPPFLAGS="$UMFPACK_INC_FLAG"
+ HAVE_UMFPACK="1"],
+ AC_MSG_WARN([umfpack.h not found in $UMFPACK_INCLUDE_PATH]))
+
+ CPPFLAGS="$REM_CPPFLAGS"
+ REM_CPPFLAGS=
+
+ REM_LDFLAGS=$LDFLAGS
+
+ # if header is found...
+ if test x$HAVE_UMFPACK = x1 ; then
+ AC_CHECK_LIB(umfpack,[main],
+ [UMFPACK_LIBS="-lumfpack"
+ UMFPACK_LDFLAGS="-L$UMFPACK_LIB_PATH"],
+ [HAVE_UMFPACK="0"
+ AC_MSG_WARN(libumfpack not found!)])
+ fi
+
+ # if lib is found...
+ if test x$HAVE_UMFPACK = x1 ; then
+ AC_CHECK_LIB(amd,[main],
+ [UMFPACK_LIBS="$UMFPACK_LIBS -lamd"
+ UMFPACK_LDFLAGS="$UMFPACK_LDFLAGS -L$UMFAMD_LIB_PATH"
+ LIBS="$LIBS $UMFPACK_LIBS"],
+ [HAVE_UMFPACK="0"
+ AC_MSG_WARN(libamd not found!)])
+ fi
+
+ LDFLAGS=$REM_LDFLAGS
+ AC_LANG_POP
+
+## end of umfpack check (--without wasn't set)
+fi
+
+# survived all tests?
+if test x$HAVE_UMFPACK = x1 ; then
+ AC_SUBST(UMFPACK_LIBS, $UMFPACK_LIBS)
+ AC_SUBST(UMFPACK_LDFLAGS, $UMFPACK_LDFLAGS)
+ AC_SUBST(UMFPACK_CPPFLAGS, $UMFPACK_CPPFLAGS)
+ AC_DEFINE(HAVE_UMFPACK, ENABLE_UMFPACK,
+ [This is only true if umfpack-library was found by configure
+ _and_ if the application uses the UMFPACK_CPPFLAGS])
+
+ # add to global list
+ DUNE_ADD_ALL_PKG([UMFPACK], [\${UMFPACK_CPPFLAGS}],
+ [\${UMFPACK_LDFLAGS}], [\${UMFPACK_LIBS}])
+
+ # set variable for summary
+ with_umfpack="yes"
+
+else
+ AC_SUBST(UMFPACK_LIBS, "")
+ AC_SUBST(UMFPACK_LDFLAGS, "")
+ AC_SUBST(UMFPACK_CPPFLAGS, "")
+
+ # set variable for summary
+ with_umfpack="no"
+fi
+
+# also tell automake
+AM_CONDITIONAL(UMFPACK, test x$HAVE_UMFPACK = x1)
+
+# reset old values
+LIBS="$ac_save_LIBS"
+CPPFLAGS="$ac_save_CPPFLAGS"
+LDFLAGS="$ac_save_LDFLAGS"
+
+ DUNE_ADD_SUMMARY_ENTRY([UMFPACK],[$with_umfpack])
+])
--- /dev/null
+#!/bin/sh
+
+# where is the autoconf-archive installed?
+ARCHDIR=/usr/share/autoconf-archive/
+# if anyone wants this as an option, tell me (Thimo)
+
+for NAME in *.m4 ; do
+ # newer version installed?
+ if test $ARCHDIR/$NAME -nt $NAME ; then
+ echo Updating $NAME
+ cp $ARCHDIR/$NAME $NAME
+ fi
+done
--- /dev/null
+# $Id$
+# searches for XDR Headers which are implicitly included by rpc.h
+# some systems don't like it when xdr.h is directly included
+
+AC_DEFUN([DUNE_PATH_XDR],[
+ AC_REQUIRE([AC_PROG_CC])
+ AC_CHECK_HEADERS(rpc/rpc.h)
+])
--- /dev/null
+add_subdirectory("bash-completion")
--- /dev/null
+SUBDIRS = bash-completion
+
+EXTRA_DIST= CMakeLists.txt
+
+# include further rules needed by Dune
+include $(top_srcdir)/am/global-rules
--- /dev/null
+add_subdirectory("completions")
--- /dev/null
+SUBDIRS = completions
+
+EXTRA_DIST= CMakeLists.txt
+
+# include further rules needed by Dune
+include $(top_srcdir)/am/global-rules
--- /dev/null
+install(FILES
+ dunecontrol
+ DESTINATION ${CMAKE_INSTALL_DATADIR}/share/bash-completion/
+)
--- /dev/null
+# $Id$
+
+completions_DATA = dunecontrol
+
+# Not all file names seem to be treated equal by _DATA.
+# inkscape.am no-check-without-lib have to be listed in
+# EXTRA_DIST to be included into the tarball.
+EXTRA_DIST = CMakeLists.txt dunecontrol
+completionsdir = $(datarootdir)/bash-completion/completions
+
+include $(top_srcdir)/am/global-rules
--- /dev/null
+# -*- shell-script -*-
+# bash completion for dunecontrol
+
+_dunecontrol_complete ()
+{
+ local COMMANDS="printdeps vcsetup update autogen configure make all exec bexec status svn git"
+ local COMMAND_OPTS="$(for i in printdeps vcsetup update autogen configure make all exec bexec status svn git; do echo --$i-opts; done)"
+ # per default we offer the list of all core modules and the advertised discretization modules
+ local MODULES="dune-common dune-grid dune-grid-howto dune-istl dune-geometry dune-localfunctions dune-pdelab dune-fem dune-fufem"
+ if test "x$DUNE_MODULES" != x; then
+ MODULES=$DUNE_MODULES
+ fi
+
+ # get cimpletion information
+ local cur prev words cword split
+ _init_completion -s || return
+
+ # check wether we already have seen a command
+ local have_command=0
+ for i in `seq $COMP_CWORD`; do
+ case ${COMP_WORDS[i]} in
+ printdeps|vcsetup|update|autogen|configure|make|all|exec|bexec|status|svn|git)
+ have_command=1
+ ;;
+ esac
+ done
+
+ # some options influence the next completion step
+ case $prev in
+ :)
+ COMPREPLY=( $(compgen -W "
+ $COMMANDS
+ " -- $cur) )
+ return 0
+ ;;
+ -h|--help)
+ return 0
+ ;;
+ --module)
+ COMPREPLY=( $(compgen -W " $MODULES " -- $cur ) )
+ compopt -o nospace
+ return 0
+ ;;
+ --only)
+ COMPREPLY=( $(compgen -W " $MODULES " -- $cur ) )
+ compopt -o nospace
+ return 0
+ ;;
+ --opts)
+ compopt -o filenames
+ COMPREPLY=( $( compgen -f -- "$cur" ) \
+ $( compgen -d -- "$cur" ) )
+ return 0
+ ;;
+# git)
+# exec __git_func_wrap __git_main
+# compopt -D
+# COMPREPLY=( $( compgen -W ":" -- $cur ) )
+# return 0
+# ;;
+ esac
+
+ # if we already have a command, we either pass an options to the command,
+ # or we add a colon for the next command
+ if test x$have_command = x1; then
+ COMPREPLY=( $(compgen -W " -- : " -- $cur ) )
+ return 0;
+ fi
+
+ # the usual dunecontrol options
+ COMPREPLY=( $(compgen -W "
+ -h --help --use-cmake --current --resume --skipfirst
+ --module= --only=
+ --opts=
+ --builddir=
+ $COMMANDS
+ $COMMAND_OPTS
+ " -- $cur)
+ )
+
+ # don't append space to options --foo=...
+ [[ $COMPREPLY == *= ]] && compopt -o nospace
+} && complete -F _dunecontrol_complete dunecontrol
--- /dev/null
+Subversion is used for revision control. The repository is located at
+'https://svn.dune-project.org/svn/dune-common'.