From 49cfbdb928442267fae6ffd6a24472a35635cffb Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Tue, 2 Oct 2018 16:11:31 +0200 Subject: [PATCH 001/111] Added comment to String constructor. --- src/TNL/String.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/TNL/String.h b/src/TNL/String.h index 0868ac44a..771629625 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -38,14 +38,15 @@ public: //! Basic constructor String(); - //! Constructor with char pointer - /*! @param prefix_cut_off says length of the prefix that is going to be omitted and - @param sufix_cut_off says the same about sufix. - */ + ////// + /// Constructor with char pointer + /// + /// @param prefix_cut_off says length of the prefix that is going to be omitted and + /// @param sufix_cut_off says the same about sufix. String( const char* c, int prefix_cut_off = 0, int sufix_cut_off = 0 ); - + String( char* c, int prefix_cut_off = 0, int sufix_cut_off = 0 ); -- GitLab From c47bdc17cff669de3880e7594cace73c19ff76ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Oberhuber?= Date: Wed, 3 Oct 2018 21:25:02 +0200 Subject: [PATCH 002/111] Tunning comments in String.h. --- src/TNL/String.h | 258 ++++++++++++++++++++++++----------------------- 1 file changed, 132 insertions(+), 126 deletions(-) diff --git a/src/TNL/String.h b/src/TNL/String.h index 771629625..36c9f7e2d 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -25,134 +25,140 @@ class String; template< typename T > String convertToString( const T& value ); -//! Class for managing strings +///// +// \brief Class for managing strings class String { - //! Pointer to char ended with zero - char* string; - - //! Length of the allocated piece of memory - int length; - -public: - //! Basic constructor - String(); - - ////// - /// Constructor with char pointer - /// - /// @param prefix_cut_off says length of the prefix that is going to be omitted and - /// @param sufix_cut_off says the same about sufix. - String( const char* c, - int prefix_cut_off = 0, - int sufix_cut_off = 0 ); - - String( char* c, - int prefix_cut_off = 0, - int sufix_cut_off = 0 ); - - - static String getType(); - - //! Copy constructor - String( const String& str ); - - //! Convert anything to a string - template< typename T > - String( T value ) - : string( nullptr ), length( 0 ) - { - setString( convertToString( value ).getString() ); - } - - //! Destructor - ~String(); - - //! Return length of the string - int getLength() const; - int getSize() const; - - //! Return currently allocated size - int getAllocatedSize() const; - - //! Reserve space for given number of characters - void setSize( int size ); - - //! Set string from given char pointer - /*! @param prefix_cut_off says length of the prefix that is going to be omitted and - @param sufix_cut_off says the same about sufix. - */ - void setString( const char* c, - int prefix_cut_off = 0, - int sufix_cut_off = 0 ); - - //! Return pointer to data - const char* getString() const; - - //! Return pointer to data - char* getString(); - - //! Operator for accesing particular chars of the string - const char& operator[]( int i ) const; - - //! Operator for accesing particular chars of the string - char& operator[]( int i ); - - /**** - * Operators for C strings - */ - String& operator=( const char* str ); - String& operator+=( const char* str ); - String operator+( const char* str ) const; - bool operator==( const char* str ) const; - bool operator!=( const char* str ) const; - - /**** - * Operators for Strings - */ - String& operator=( const String& str ); - String& operator+=( const String& str ); - String operator+( const String& str ) const; - bool operator==( const String& str ) const; - bool operator!=( const String& str ) const; - - /**** - * Operators for single characters - */ - String& operator=( char str ); - String& operator+=( char str ); - String operator+( char str ) const; - bool operator==( char str ) const; - bool operator!=( char str ) const; - - //! Cast to bool operator - operator bool() const; - - //! Cast to bool with negation operator - bool operator!() const; - - String replace( const String& pattern, - const String& replaceWith, - int count = 0 ) const; - - String strip( char strip = ' ' ) const; - - //! Split the string into list of strings w.r.t. given separator. - int split( Containers::List< String >& list, const char separator = ' ' ) const; - - //! Write to a binary file - bool save( File& file ) const; - - //! Read from binary file - bool load( File& file ); - - //! Broadcast to other nodes in MPI cluster -// void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); - - //! Read one line from given stream. - bool getLine( std::istream& stream ); - - friend std::ostream& operator<<( std::ostream& stream, const String& str ); + public: + + ///// + /// \brief Basic constructor + String(); + + ///// + /// \brief Constructor with char pointer. + /// Constructor with char pointer. + /// @param prefix_cut_off says length of the prefix that is going to be omitted and + /// @param sufix_cut_off says the same about suffix. + String( const char* c, + int prefix_cut_off = 0, + int sufix_cut_off = 0 ); + + String( char* c, + int prefix_cut_off = 0, + int sufix_cut_off = 0 ); + + + static String getType(); + + //! Copy constructor + String( const String& str ); + + //! Convert anything to a string + template< typename T > + String( T value ) + : string( nullptr ), length( 0 ) + { + setString( convertToString( value ).getString() ); + } + + //! Destructor + ~String(); + + //! Return length of the string + int getLength() const; + int getSize() const; + + //! Return currently allocated size + int getAllocatedSize() const; + + //! Reserve space for given number of characters + void setSize( int size ); + + //! Set string from given char pointer + /*! @param prefix_cut_off says length of the prefix that is going to be omitted and + @param sufix_cut_off says the same about sufix. + */ + void setString( const char* c, + int prefix_cut_off = 0, + int sufix_cut_off = 0 ); + + //! Return pointer to data + const char* getString() const; + + //! Return pointer to data + char* getString(); + + //! Operator for accesing particular chars of the string + const char& operator[]( int i ) const; + + //! Operator for accesing particular chars of the string + char& operator[]( int i ); + + /**** + * Operators for C strings + */ + String& operator=( const char* str ); + String& operator+=( const char* str ); + String operator+( const char* str ) const; + bool operator==( const char* str ) const; + bool operator!=( const char* str ) const; + + /**** + * Operators for Strings + */ + String& operator=( const String& str ); + String& operator+=( const String& str ); + String operator+( const String& str ) const; + bool operator==( const String& str ) const; + bool operator!=( const String& str ) const; + + /**** + * Operators for single characters + */ + String& operator=( char str ); + String& operator+=( char str ); + String operator+( char str ) const; + bool operator==( char str ) const; + bool operator!=( char str ) const; + + //! Cast to bool operator + operator bool() const; + + //! Cast to bool with negation operator + bool operator!() const; + + String replace( const String& pattern, + const String& replaceWith, + int count = 0 ) const; + + String strip( char strip = ' ' ) const; + + //! Split the string into list of strings w.r.t. given separator. + int split( Containers::List< String >& list, const char separator = ' ' ) const; + + //! Write to a binary file + bool save( File& file ) const; + + //! Read from binary file + bool load( File& file ); + + //! Broadcast to other nodes in MPI cluster + // void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); + + //! Read one line from given stream. + bool getLine( std::istream& stream ); + + friend std::ostream& operator<<( std::ostream& stream, const String& str ); + + protected: + //! Pointer to char ended with zero + char* string; + + //! Length of the allocated piece of memory + int length; + + }; String operator+( char string1, const String& string2 ); -- GitLab From 2a128df3f73ca6fea0e6ba451fafdc57358f8333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Oberhuber?= Date: Sun, 7 Oct 2018 18:33:10 +0200 Subject: [PATCH 003/111] Deleted Doxyfile in src/TNL. --- src/TNL/Doxyfile | 1514 ---------------------------------------------- 1 file changed, 1514 deletions(-) delete mode 100644 src/TNL/Doxyfile diff --git a/src/TNL/Doxyfile b/src/TNL/Doxyfile deleted file mode 100644 index 4fb5d22f9..000000000 --- a/src/TNL/Doxyfile +++ /dev/null @@ -1,1514 +0,0 @@ -# Doxyfile 1.6.1 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = tnl - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = ../Release/src - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = YES - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# 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 = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = - -# 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 = - -# 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. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = NO - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 3 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it parses. -# With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this tag. -# The format is ext=language, where ext is a file extension, and language is one of -# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, -# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat -# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), -# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. - -EXTENSION_MAPPING = - -# 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 = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen to replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. - -TYPEDEF_HIDES_STRUCT = NO - -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penality. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will rougly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols - -SYMBOL_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespace are hidden. - -EXTRACT_ANON_NSPACES = NO - -# 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 = NO - -# 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 = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# 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 = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = 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. - -SHOW_DIRECTORIES = NO - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by -# doxygen. The layout file controls the global structure of the generated output files -# in an output format independent way. The create the layout file that represents -# doxygen's defaults, run doxygen with the -l option. You can optionally specify a -# file name after the option, if omitted DoxygenLayout.xml will be used as the name -# of the layout file. - -LAYOUT_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# 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 = - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 - -FILE_PATTERNS = - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# 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 = - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# 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 = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# 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 = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. - -REFERENCES_LINK_SOURCE = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = NO - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# 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. - -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. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = NO - -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. - -GENERATE_DOCSET = NO - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. - -CHM_INDEX_ENCODING = - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER -# are set, an additional index file will be generated that can be used as input for -# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated -# HTML documentation. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace - -QHP_NAMESPACE = - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders - -QHP_VIRTUAL_FOLDER = doc - -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. -# For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see -# Qt Help Project / Custom Filters. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's -# filter section matches. -# Qt Help Project / Filter Attributes. - -QHP_SECT_FILTER_ATTRS = - -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. - -QHG_LOCATION = - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. - -GENERATE_TREEVIEW = NO - -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. - -USE_INLINE_TREES = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. - -FORMULA_FONTSIZE = 10 - -# When the SEARCHENGINE tag is enable doxygen will generate a search box for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP) or Qt help (GENERATE_QHP) -# there is already a search function so this one should typically -# be disabled. - -SEARCHENGINE = YES - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = YES - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = YES - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = YES - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -# If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER. - -LATEX_SOURCE_CODE = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. -# This is useful -# if you want to understand what is going on. -# On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# 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 = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more -# powerful graphs. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = NO - -# By default doxygen will write a font called FreeSans.ttf to the output -# directory and reference it in all dot files that doxygen generates. This -# font does not include all possible unicode characters however, so when you need -# these (or just want a differently looking font) you can specify the font name -# using DOT_FONTNAME. You need need to make sure dot is able to find the font, -# which can be done by putting it in a standard location or by setting the -# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory -# containing the font. - -DOT_FONTNAME = FreeSans - -# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. -# The default size is 10pt. - -DOT_FONTSIZE = 10 - -# By default doxygen will tell dot to use the output directory to look for the -# FreeSans.ttf font (which doxygen will put there itself). If you specify a -# different font using DOT_FONTNAME you can set the path where dot -# can find it using this tag. - -DOT_FONTPATH = - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = NO - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. - -CALLER_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of -# a graph (i.e. they become hard to read). - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = YES - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES -- GitLab From 440ca336261a32fab6c25240cf3c43a05a6dfc49 Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber Date: Wed, 17 Oct 2018 15:17:21 +0200 Subject: [PATCH 004/111] Added string test getLine. --- src/UnitTests/StringTest.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/UnitTests/StringTest.cpp b/src/UnitTests/StringTest.cpp index 665145558..dcf500796 100644 --- a/src/UnitTests/StringTest.cpp +++ b/src/UnitTests/StringTest.cpp @@ -284,6 +284,23 @@ TEST( StringTest, SaveLoad ) EXPECT_EQ( std::remove( "test-file.tnl" ), 0 ); }; + +TEST( StringTest, getLine ) +{ + std::stringstream str; + str << "Line 1" << std::endl; + str << "Line 2" << std::endl; + str.seekg( 0 ); + + String s; + + s.getLine( str ); + EXPECT_EQ( s, "Line 1" ); + + s.getLine( str ); + EXPECT_EQ( s, "Line 2" ); +}; + #endif -- GitLab From 71d8535571e0d44ae7c4b5659eceb98e3af5fb79 Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber Date: Wed, 17 Oct 2018 15:44:02 +0200 Subject: [PATCH 005/111] Added FileNameTest. --- src/UnitTests/CMakeLists.txt | 12 ++++----- src/UnitTests/FileNameTest.cpp | 47 ++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 src/UnitTests/FileNameTest.cpp diff --git a/src/UnitTests/CMakeLists.txt b/src/UnitTests/CMakeLists.txt index 842ce9f2c..cf0fc8c47 100644 --- a/src/UnitTests/CMakeLists.txt +++ b/src/UnitTests/CMakeLists.txt @@ -31,17 +31,17 @@ else() tnl ) endif() +ADD_EXECUTABLE( FileNameTest FileNameTest.cpp ) +TARGET_COMPILE_OPTIONS( FileNameTest PRIVATE ${CXX_TESTS_FLAGS} ) +TARGET_LINK_LIBRARIES( FileNameTest ${GTEST_BOTH_LIBRARIES} tnl ) + ADD_EXECUTABLE( StringTest StringTest.cpp ) TARGET_COMPILE_OPTIONS( StringTest PRIVATE ${CXX_TESTS_FLAGS} ) -TARGET_LINK_LIBRARIES( StringTest - ${GTEST_BOTH_LIBRARIES} - tnl ) +TARGET_LINK_LIBRARIES( StringTest ${GTEST_BOTH_LIBRARIES} tnl ) ADD_EXECUTABLE( ObjectTest ObjectTest.cpp ) TARGET_COMPILE_OPTIONS( ObjectTest PRIVATE ${CXX_TESTS_FLAGS} ) -TARGET_LINK_LIBRARIES( ObjectTest - ${GTEST_BOTH_LIBRARIES} - tnl ) +TARGET_LINK_LIBRARIES( ObjectTest ${GTEST_BOTH_LIBRARIES} tnl ) ADD_EXECUTABLE( SaveAndLoadMeshfunctionTest SaveAndLoadMeshfunctionTest.cpp ) TARGET_COMPILE_OPTIONS( SaveAndLoadMeshfunctionTest PRIVATE ${CXX_TESTS_FLAGS} ) diff --git a/src/UnitTests/FileNameTest.cpp b/src/UnitTests/FileNameTest.cpp new file mode 100644 index 000000000..3f71be146 --- /dev/null +++ b/src/UnitTests/FileNameTest.cpp @@ -0,0 +1,47 @@ +/*************************************************************************** + FileNameTest.cpp - description + ------------------- + begin : Oct 17, 2018 + copyright : (C) 2018 by Tomas Oberhuber + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by Nina Dzugasova + +#ifdef HAVE_GTEST +#include +#endif + +#include + +using namespace TNL; + +#ifdef HAVE_GTEST +TEST( FileNameTest, Constructor ) +{ + /*String str1( "string1" ); + String str2( "xxxstring2", 3 ); + String str3( "string3xxx", 0, 3 ); + String str4( "xxxstring4xxx", 3, 3 ); + + EXPECT_EQ( strcmp( str1.getString(), "string1" ), 0 ); + EXPECT_EQ( strcmp( str2.getString(), "string2" ), 0 ); + EXPECT_EQ( strcmp( str3.getString(), "string3" ), 0 ); + EXPECT_EQ( strcmp( str4.getString(), "string4" ), 0 );*/ +} +#endif + + +#include "GtestMissingError.h" +int main( int argc, char* argv[] ) +{ +#ifdef HAVE_GTEST + ::testing::InitGoogleTest( &argc, argv ); + return RUN_ALL_TESTS(); +#else + throw GtestMissingError(); +#endif +} + -- GitLab From e1a71c012384bbf5b1b91f834bda9a29b347bf06 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Wed, 17 Oct 2018 16:18:58 +0200 Subject: [PATCH 006/111] Added tests(GetSize, GetAllocatedSize, GetString) and modified tests (SetString, replace) in StringTest. --- src/UnitTests/StringTest.cpp | 40 ++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/UnitTests/StringTest.cpp b/src/UnitTests/StringTest.cpp index 665145558..ff95a8db8 100644 --- a/src/UnitTests/StringTest.cpp +++ b/src/UnitTests/StringTest.cpp @@ -62,6 +62,34 @@ TEST( StringTest, ConstructorWithNumber ) EXPECT_EQ( strcmp( string4.getString(), "false" ), 0 ); } +TEST( StringTest, GetSize ) +{ + String str1( "string" ); + String str2( "12345" ); + String str3( "string3" ); + String str4( "String_4" ); + String str5( "Last String" ); + + EXPECT_EQ( str1.getSize(), 6 ); + EXPECT_EQ( str2.getSize(), 5 ); + EXPECT_EQ( str3.getSize(), 7 ); + EXPECT_EQ( str4.getSize(), 8 ); + EXPECT_EQ( str5.getSize(), 11 ); + + EXPECT_EQ( str1.getLength(), 6 ); + EXPECT_EQ( str2.getLength(), 5 ); + EXPECT_EQ( str3.getLength(), 7 ); + EXPECT_EQ( str4.getLength(), 8 ); + EXPECT_EQ( str5.getLength(), 11 ); +} + +TEST( StringTest, GetAllocatedSize ) +{ + String str( "MeineKleine" ); + + EXPECT_EQ( str.getAllocatedSize(), 256 ); +} + TEST( StringTest, SetSize ) { String str; @@ -85,6 +113,15 @@ TEST( StringTest, SetString ) EXPECT_EQ( strcmp( str2.getString(), "string2" ), 0 ); EXPECT_EQ( strcmp( str3.getString(), "string3" ), 0 ); EXPECT_EQ( strcmp( str4.getString(), "string4" ), 0 ); + + str4.setString( "string4_2", 0, 2 ); + EXPECT_EQ( strcmp( str4.getString(), "string4" ), 0 ); +} + +TEST( StringTest, GetString ) +{ + String str( "MyString" ); + EXPECT_EQ( strcmp( str.getString(), "MyString" ), 0 ); } TEST( StringTest, IndexingOperator ) @@ -229,6 +266,9 @@ TEST( StringTest, replace ) EXPECT_EQ( String( "string" ).replace( "ing", "bc" ), "strbc" ); EXPECT_EQ( String( "abracadabra" ).replace( "ab", "CAT" ), "CATracadCATra" ); EXPECT_EQ( String( "abracadabra" ).replace( "ab", "CAT", 1 ), "CATracadabra" ); + EXPECT_NE( String( "abracadabra" ).replace( "ab", "CAT", 2 ), "abracadCATra" ); + EXPECT_NE( String( "abracadabra" ).replace( "ab", "CAT", 2 ), "abracadabra" ); + EXPECT_EQ( String( "abracadabra" ).replace( "ab", "CAT", 2 ), "CATracadCATra" ); } TEST( StringTest, strip ) -- GitLab From 62648968c362554b297e4d9b7e4759b70040acf2 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Fri, 19 Oct 2018 16:44:18 +0200 Subject: [PATCH 007/111] Added documentation of String. Found error in StringTest split function. --- CMakeLists.txt | 43 +- TODO | 17 +- src/Benchmarks/BLAS/array-operations.h | 5 +- src/Benchmarks/BLAS/tnl-benchmark-blas.h | 39 +- src/Benchmarks/Benchmarks.h | 133 +- src/Benchmarks/CMakeLists.txt | 1 + src/Benchmarks/DistSpMV/CMakeLists.txt | 11 + src/Benchmarks/DistSpMV/ordering.h | 21 + .../tnl-benchmark-distributed-spmv.cpp | 11 + .../tnl-benchmark-distributed-spmv.cu | 11 + .../DistSpMV/tnl-benchmark-distributed-spmv.h | 357 ++++ src/Benchmarks/LinearSolvers/CMakeLists.txt | 13 +- .../LinearSolvers/CuSolverWrapper.h | 135 ++ src/Benchmarks/LinearSolvers/benchmarks.h | 215 +++ .../tnl-benchmark-linear-solvers.cpp | 10 - .../tnl-benchmark-linear-solvers.cu | 10 - .../tnl-benchmark-linear-solvers.h | 685 ++++++-- .../Algorithms/Multireduction_impl.h | 94 +- .../Containers/Algorithms/Reduction_impl.h | 48 +- .../DistributedContainers/DistributedArray.h | 142 ++ .../DistributedArrayView.h | 152 ++ .../DistributedArrayView_impl.h | 371 ++++ .../DistributedArray_impl.h | 352 ++++ .../DistributedContainers/DistributedMatrix.h | 186 ++ .../DistributedMatrix_impl.h | 360 ++++ .../DistributedContainers/DistributedSpMV.h | 221 +++ .../DistributedContainers/DistributedVector.h | 139 ++ .../DistributedVectorView.h | 137 ++ .../DistributedVectorView_impl.h | 555 ++++++ .../DistributedVector_impl.h | 566 ++++++ src/TNL/DistributedContainers/Partitioner.h | 73 + src/TNL/DistributedContainers/Subrange.h | 123 ++ src/TNL/Doxyfile | 1514 ----------------- src/TNL/Matrices/CMakeLists.txt | 15 +- src/TNL/Matrices/Sparse.h | 10 +- src/TNL/Matrices/SparseOperations.h | 51 + src/TNL/Matrices/SparseOperations_impl.h | 364 ++++ src/TNL/Matrices/Sparse_impl.h | 141 -- src/TNL/Solvers/Linear/BICGStab.h | 6 +- src/TNL/Solvers/Linear/BICGStabL.h | 21 +- src/TNL/Solvers/Linear/BICGStabL_impl.h | 107 +- src/TNL/Solvers/Linear/BICGStab_impl.h | 18 +- src/TNL/Solvers/Linear/CMakeLists.txt | 2 - src/TNL/Solvers/Linear/CWYGMRES.h | 115 -- src/TNL/Solvers/Linear/CWYGMRES_impl.h | 633 ------- src/TNL/Solvers/Linear/GMRES.h | 111 +- src/TNL/Solvers/Linear/GMRES_impl.h | 726 +++++--- src/TNL/Solvers/Linear/LinearSolver.h | 7 +- .../Linear/Preconditioners/CMakeLists.txt | 1 + .../Solvers/Linear/Preconditioners/Diagonal.h | 31 +- .../Linear/Preconditioners/Diagonal_impl.h | 132 +- src/TNL/Solvers/Linear/Preconditioners/ILU0.h | 69 +- .../Linear/Preconditioners/ILU0_impl.h | 314 ++-- src/TNL/Solvers/Linear/Preconditioners/ILUT.h | 23 +- .../Linear/Preconditioners/ILUT_impl.h | 191 +-- .../Linear/Preconditioners/Preconditioner.h | 9 +- .../Linear/Preconditioners/TriangularSolve.h | 117 ++ src/TNL/Solvers/Linear/TFQMR.h | 8 +- src/TNL/Solvers/Linear/TFQMR_impl.h | 23 +- src/TNL/Solvers/Linear/Traits.h | 102 ++ src/TNL/Solvers/LinearSolverTypeResolver.h | 5 +- src/TNL/Solvers/SolverConfig_impl.h | 5 - src/TNL/String.h | 102 +- src/UnitTests/CMakeLists.txt | 13 +- src/UnitTests/Containers/CMakeLists.txt | 15 + .../Containers/MultireductionTest.cpp | 1 + .../Containers/MultireductionTest.cu | 1 + src/UnitTests/Containers/MultireductionTest.h | 132 ++ src/UnitTests/Containers/VectorTest.h | 2 +- .../DistributedContainers/CMakeLists.txt | 50 + .../DistributedArrayTest.cpp | 1 + .../DistributedArrayTest.cu | 1 + .../DistributedArrayTest.h | 346 ++++ .../DistributedMatrixTest.cpp | 1 + .../DistributedMatrixTest.cu | 1 + .../DistributedMatrixTest.h | 296 ++++ .../DistributedVectorTest.cpp | 1 + .../DistributedVectorTest.cu | 1 + .../DistributedVectorTest.h | 411 +++++ src/UnitTests/FileNameTest.cpp | 47 + src/UnitTests/StringTest.cpp | 25 + 81 files changed, 8111 insertions(+), 3443 deletions(-) create mode 100644 src/Benchmarks/DistSpMV/CMakeLists.txt create mode 100644 src/Benchmarks/DistSpMV/ordering.h create mode 100644 src/Benchmarks/DistSpMV/tnl-benchmark-distributed-spmv.cpp create mode 100644 src/Benchmarks/DistSpMV/tnl-benchmark-distributed-spmv.cu create mode 100644 src/Benchmarks/DistSpMV/tnl-benchmark-distributed-spmv.h create mode 100644 src/Benchmarks/LinearSolvers/CuSolverWrapper.h create mode 100644 src/Benchmarks/LinearSolvers/benchmarks.h create mode 100644 src/TNL/DistributedContainers/DistributedArray.h create mode 100644 src/TNL/DistributedContainers/DistributedArrayView.h create mode 100644 src/TNL/DistributedContainers/DistributedArrayView_impl.h create mode 100644 src/TNL/DistributedContainers/DistributedArray_impl.h create mode 100644 src/TNL/DistributedContainers/DistributedMatrix.h create mode 100644 src/TNL/DistributedContainers/DistributedMatrix_impl.h create mode 100644 src/TNL/DistributedContainers/DistributedSpMV.h create mode 100644 src/TNL/DistributedContainers/DistributedVector.h create mode 100644 src/TNL/DistributedContainers/DistributedVectorView.h create mode 100644 src/TNL/DistributedContainers/DistributedVectorView_impl.h create mode 100644 src/TNL/DistributedContainers/DistributedVector_impl.h create mode 100644 src/TNL/DistributedContainers/Partitioner.h create mode 100644 src/TNL/DistributedContainers/Subrange.h delete mode 100644 src/TNL/Doxyfile create mode 100644 src/TNL/Matrices/SparseOperations.h create mode 100644 src/TNL/Matrices/SparseOperations_impl.h delete mode 100644 src/TNL/Solvers/Linear/CWYGMRES.h delete mode 100644 src/TNL/Solvers/Linear/CWYGMRES_impl.h create mode 100644 src/TNL/Solvers/Linear/Preconditioners/TriangularSolve.h create mode 100644 src/TNL/Solvers/Linear/Traits.h create mode 100644 src/UnitTests/Containers/MultireductionTest.cpp create mode 100644 src/UnitTests/Containers/MultireductionTest.cu create mode 100644 src/UnitTests/Containers/MultireductionTest.h create mode 100644 src/UnitTests/DistributedContainers/CMakeLists.txt create mode 100644 src/UnitTests/DistributedContainers/DistributedArrayTest.cpp create mode 100644 src/UnitTests/DistributedContainers/DistributedArrayTest.cu create mode 100644 src/UnitTests/DistributedContainers/DistributedArrayTest.h create mode 100644 src/UnitTests/DistributedContainers/DistributedMatrixTest.cpp create mode 100644 src/UnitTests/DistributedContainers/DistributedMatrixTest.cu create mode 100644 src/UnitTests/DistributedContainers/DistributedMatrixTest.h create mode 100644 src/UnitTests/DistributedContainers/DistributedVectorTest.cpp create mode 100644 src/UnitTests/DistributedContainers/DistributedVectorTest.cu create mode 100644 src/UnitTests/DistributedContainers/DistributedVectorTest.h create mode 100644 src/UnitTests/FileNameTest.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index fc377eee6..8784170f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,9 +37,9 @@ option(WITH_TEMPLATES_INSTANTIATION "Enable explicit template instantiation" OFF set( TNL_TARGET_INCLUDE_DIRECTORY "include/TNL" ) set( TNL_TARGET_DATA_DIRECTORY "share/TNL" ) -set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") - -include( OptimizeForArchitecture ) +# set cmake's include path so that we can include modules from +# the cmake directory in the TNL repository +set( CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" ) # Note that in cmake 3.10 the FindOpenMP module is broken - it does not work when # CMAKE_EXECUTABLE_SUFFIX is not empty, see https://www.mail-archive.com/cmake@cmake.org/msg56886.html @@ -93,9 +93,12 @@ set( CMAKE_SHARED_LINKER_FLAGS "" ) set( CMAKE_SHARED_LINKER_FLAGS_DEBUG "-rdynamic" ) set( CMAKE_SHARED_LINKER_FLAGS_RELEASE "" ) -get_filename_component( CXX_COMPILER_NAME ${CMAKE_CXX_COMPILER} NAME ) -if( CXX_COMPILER_NAME MATCHES "icpc" ) - message( "Intel compiler detected..." ) +# disable GCC's infamous "maybe-uninitialized" warning (it produces mostly false positives) +if( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" ) + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-maybe-uninitialized" ) +endif() + +if( CMAKE_CXX_COMPILER_ID STREQUAL "Intel" ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_ICPC -wd2568 -wd2571 -wd2570") ##### # Check for MIC @@ -124,6 +127,7 @@ endif() ##### # Check for MPI -- poznej podle vraperu compileru -- da se testovat preklad bez MPI # +get_filename_component( CXX_COMPILER_NAME ${CMAKE_CXX_COMPILER} NAME ) if( ${CXX_COMPILER_NAME} STREQUAL "mpicxx" ) message( "MPI compiler detected." ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_MPI" ) @@ -240,7 +244,6 @@ endif() # Check for OpenMP # if( OPENMP_FOUND AND ${WITH_OPENMP} ) - message( "Enabled OpenMP support." ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_OPENMP ${OpenMP_CXX_FLAGS}" ) endif() @@ -454,19 +457,19 @@ INCLUDE( CPack ) # Print custom build options message( "-- Build options:" ) -message( " OFFLINE_BUILD=${OFFLINE_BUILD}" ) -message( " WITH_MIC=${WITH_MIC}" ) -message( " WITH_CUDA=${WITH_CUDA}" ) -message( " WITH_CUDA_ARCH=${WITH_CUDA_ARCH}" ) -message( " WITH_OPENMP=${WITH_OPENMP}" ) -message( " WITH_GMP=${WITH_GMP}" ) -message( " WITH_TESTS=${WITH_TESTS}" ) -message( " WITH_COVERAGE=${WITH_COVERAGE}" ) -message( " WITH_EXAMPLES=${WITH_EXAMPLES}" ) -message( " WITH_TOOLS=${WITH_TOOLS}" ) -message( " WITH_BENCHMARKS=${WITH_BENCHMARKS}" ) -message( " WITH_PYTHON=${WITH_PYTHON}" ) -message( " WITH_TEMPLATES_INSTANTIATION=${WITH_TEMPLATES_INSTANTIATION}" ) +message( " OFFLINE_BUILD = ${OFFLINE_BUILD}" ) +message( " WITH_MIC = ${WITH_MIC}" ) +message( " WITH_CUDA = ${WITH_CUDA}" ) +message( " WITH_CUDA_ARCH = ${WITH_CUDA_ARCH}" ) +message( " WITH_OPENMP = ${WITH_OPENMP}" ) +message( " WITH_GMP = ${WITH_GMP}" ) +message( " WITH_TESTS = ${WITH_TESTS}" ) +message( " WITH_COVERAGE = ${WITH_COVERAGE}" ) +message( " WITH_EXAMPLES = ${WITH_EXAMPLES}" ) +message( " WITH_TOOLS = ${WITH_TOOLS}" ) +message( " WITH_BENCHMARKS = ${WITH_BENCHMARKS}" ) +message( " WITH_PYTHON = ${WITH_PYTHON}" ) +message( " WITH_TEMPLATES_INSTANTIATION = ${WITH_TEMPLATES_INSTANTIATION}" ) # Print compiler options message( "-- Compiler options:" ) message( " CMAKE_CXX_FLAGS = ${CMAKE_CXX_FLAGS}" ) diff --git a/TODO b/TODO index dbbaae07b..339a813a4 100644 --- a/TODO +++ b/TODO @@ -21,7 +21,7 @@ TODO: - implementovat tuple pro snazsi a snad efektivnejsi prenos dat na GPU - nebylo by nutne definovat pomocne datove structury pro traverser - data by se na hostu preskupila do souvisleho bloku dat a ten se prenesl najednou - + - JK: tohle je zbytecny resit, od toho je lambda capture - staci prepsat traversery obecne pomoci ParallelFor TODO: CUDA unified memory - pretizit operator new s cudaMallocManaged, pak by bylo mozne vytvaret CUDA objekty pristupne pro host a device @@ -33,17 +33,18 @@ se s nimi pracovat postaru TODO: implementace maticovych resicu - * Gaussova eliminace - * SOR metoda - * Jacobiho metoda - * IDR metody + - Gaussova eliminace + - IDR metody +existujici solvery ktere je treba dodelat + - CG (nema predpodmineni, otestovat) + - SOR, jacobi (nejsou paralelni, otestovat ze funguji pro vsechny typy matic) TODO: Nahradit sablonovy parametr dimenze sitove entity za typ entity. Pak by se mohlo zkusit, napriklad u gridu odvozovat entity, ktere obsahuji predpocitane indexy pro dopredne, zpetne, nebo centralni diference. Uzivatel by si mohl definovat vlastni entity. Mohlo by to zvysit efektivitu. U nestrukturovanych siti by se do entit mohly doplnovat ukazatele na struktury s dalsimi informacemi jako - objemy nebo delky entyt apod. - za tim ucelem nahradit setIndex v grdi entity za update(), aby to bylo obecnejsi + objemy nebo delky entit apod. + za tim ucelem nahradit setIndex v grid entity za update(), aby to bylo obecnejsi -TODO: metodu pro tnlString pro nahrazeni napr. podretezce XXXXX indexem 00001 tj. uXXXXX.bin -> u00001.bin +TODO: metodu pro String pro nahrazeni napr. podretezce XXXXX indexem 00001 tj. uXXXXX.bin -> u00001.bin to by melo byt robustnejsi, nez doposavadni pristup diff --git a/src/Benchmarks/BLAS/array-operations.h b/src/Benchmarks/BLAS/array-operations.h index aacdb9cc6..724869c92 100644 --- a/src/Benchmarks/BLAS/array-operations.h +++ b/src/Benchmarks/BLAS/array-operations.h @@ -102,9 +102,8 @@ benchmarkArrayOperations( Benchmark & benchmark, }; #ifdef HAVE_CUDA benchmark.setOperation( "copy (operator=)", datasetSize, copyBasetime ); - benchmark.time( reset1, - "CPU->GPU", copyAssignHostCuda, - "GPU->CPU", copyAssignCudaHost ); + benchmark.time( reset1, "CPU->GPU", copyAssignHostCuda ); + benchmark.time( reset1, "GPU->CPU", copyAssignCudaHost ); #endif diff --git a/src/Benchmarks/BLAS/tnl-benchmark-blas.h b/src/Benchmarks/BLAS/tnl-benchmark-blas.h index ffabe82be..4f6d63022 100644 --- a/src/Benchmarks/BLAS/tnl-benchmark-blas.h +++ b/src/Benchmarks/BLAS/tnl-benchmark-blas.h @@ -13,8 +13,7 @@ #pragma once #include -#include -#include +#include #include #include @@ -26,9 +25,6 @@ using namespace TNL; using namespace TNL::Benchmarks; -// TODO: should benchmarks check the result of the computation? - - template< typename Real > void runBlasBenchmarks( Benchmark & benchmark, @@ -146,38 +142,7 @@ main( int argc, char* argv[] ) Benchmark benchmark( loops, verbose ); // prepare global metadata - const int cpu_id = 0; - Devices::CacheSizes cacheSizes = Devices::SystemInfo::getCPUCacheSizes( cpu_id ); - String cacheInfo = String( cacheSizes.L1data ) + ", " - + String( cacheSizes.L1instruction ) + ", " - + String( cacheSizes.L2 ) + ", " - + String( cacheSizes.L3 ); -#ifdef HAVE_CUDA - const int activeGPU = Devices::CudaDeviceInfo::getActiveDevice(); - const String deviceArch = String( Devices::CudaDeviceInfo::getArchitectureMajor( activeGPU ) ) + "." + - String( Devices::CudaDeviceInfo::getArchitectureMinor( activeGPU ) ); -#endif - Benchmark::MetadataMap metadata { - { "host name", Devices::SystemInfo::getHostname() }, - { "architecture", Devices::SystemInfo::getArchitecture() }, - { "system", Devices::SystemInfo::getSystemName() }, - { "system release", Devices::SystemInfo::getSystemRelease() }, - { "start time", Devices::SystemInfo::getCurrentTime() }, - { "CPU model name", Devices::SystemInfo::getCPUModelName( cpu_id ) }, - { "CPU cores", Devices::SystemInfo::getNumberOfCores( cpu_id ) }, - { "CPU threads per core", Devices::SystemInfo::getNumberOfThreads( cpu_id ) / Devices::SystemInfo::getNumberOfCores( cpu_id ) }, - { "CPU max frequency (MHz)", Devices::SystemInfo::getCPUMaxFrequency( cpu_id ) / 1e3 }, - { "CPU cache sizes (L1d, L1i, L2, L3) (kiB)", cacheInfo }, -#ifdef HAVE_CUDA - { "GPU name", Devices::CudaDeviceInfo::getDeviceName( activeGPU ) }, - { "GPU architecture", deviceArch }, - { "GPU CUDA cores", Devices::CudaDeviceInfo::getCudaCores( activeGPU ) }, - { "GPU clock rate (MHz)", (double) Devices::CudaDeviceInfo::getClockRate( activeGPU ) / 1e3 }, - { "GPU global memory (GB)", (double) Devices::CudaDeviceInfo::getGlobalMemory( activeGPU ) / 1e9 }, - { "GPU memory clock rate (MHz)", (double) Devices::CudaDeviceInfo::getMemoryClockRate( activeGPU ) / 1e3 }, - { "GPU memory ECC enabled", Devices::CudaDeviceInfo::getECCEnabled( activeGPU ) }, -#endif - }; + Benchmark::MetadataMap metadata = getHardwareMetadata(); if( precision == "all" || precision == "float" ) runBlasBenchmarks< float >( benchmark, metadata, minSize, maxSize, sizeStepFactor, loops, elementsPerRow ); diff --git a/src/Benchmarks/Benchmarks.h b/src/Benchmarks/Benchmarks.h index 60decddc8..4b0c62271 100644 --- a/src/Benchmarks/Benchmarks.h +++ b/src/Benchmarks/Benchmarks.h @@ -16,11 +16,18 @@ #include #include #include +#include +#include #include #include #include +#include +#include +#include +#include + namespace TNL { namespace Benchmarks { @@ -64,7 +71,7 @@ timeFunction( ComputeFunction compute, timer.stop(); } - return timer.getRealTime(); + return timer.getRealTime() / loops; } @@ -75,8 +82,8 @@ public: using MetadataMap = std::map< const char*, String >; using MetadataColumns = std::vector; - using HeaderElements = std::initializer_list< String >; - using RowElements = std::initializer_list< double >; + using HeaderElements = std::vector< String >; + using RowElements = std::vector< double >; Logging( bool verbose = true ) : verbose(verbose) @@ -109,8 +116,6 @@ public: writeTableHeader( const String & spanningElement, const HeaderElements & subElements ) { - using namespace std; - if( verbose && header_changed ) { for( auto & it : metadataColumns ) { std::cout << std::setw( 20 ) << it.first; @@ -163,8 +168,6 @@ public: writeTableRow( const String & spanningElement, const RowElements & subElements ) { - using namespace std; - if( verbose ) { for( auto & it : metadataColumns ) { std::cout << std::setw( 20 ) << it.second; @@ -278,6 +281,27 @@ protected: }; +struct BenchmarkResult +{ + using HeaderElements = Logging::HeaderElements; + using RowElements = Logging::RowElements; + + double bandwidth = std::numeric_limits::quiet_NaN(); + double time = std::numeric_limits::quiet_NaN(); + double speedup = std::numeric_limits::quiet_NaN(); + + virtual HeaderElements getTableHeader() const + { + return HeaderElements({"bandwidth", "time", "speedup"}); + } + + virtual RowElements getRowElements() const + { + return RowElements({ bandwidth, time, speedup }); + } +}; + + class Benchmark : protected Logging { @@ -305,7 +329,6 @@ public: { closeTable(); writeTitle( title ); - monitor.setStage( title.getString() ); } // Marks the start of a new benchmark (with custom metadata) @@ -315,7 +338,6 @@ public: { closeTable(); writeTitle( title ); - monitor.setStage( title.getString() ); // add loops to metadata metadata["loops"] = String(loops); writeMetadata( metadata ); @@ -342,6 +364,7 @@ public: const double datasetSize = 0.0, // in GB const double baseTime = 0.0 ) { + monitor.setStage( operation.getString() ); if( metadataColumns.size() > 0 && String(metadataColumns[ 0 ].first) == "operation" ) { metadataColumns[ 0 ].second = operation; } @@ -393,43 +416,45 @@ public: double time( ResetFunction reset, const String & performer, - ComputeFunction & compute ) + ComputeFunction & compute, + BenchmarkResult & result ) { - double time; - if( verbose ) { - // run the monitor main loop - Solvers::SolverMonitorThread monitor_thread( monitor ); - time = timeFunction( compute, reset, loops, monitor ); + result.time = std::numeric_limits::quiet_NaN(); + try { + if( verbose ) { + // run the monitor main loop + Solvers::SolverMonitorThread monitor_thread( monitor ); + result.time = timeFunction( compute, reset, loops, monitor ); + } + else { + result.time = timeFunction( compute, reset, loops, monitor ); + } } - else { - time = timeFunction( compute, reset, loops, monitor ); + catch ( const std::exception& e ) { + std::cerr << "timeFunction failed due to a C++ exception with description: " << e.what() << std::endl; } - const double bandwidth = datasetSize / time; - const double speedup = this->baseTime / time; + result.bandwidth = datasetSize / result.time; + result.speedup = this->baseTime / result.time; if( this->baseTime == 0.0 ) - this->baseTime = time; + this->baseTime = result.time; - writeTableHeader( performer, HeaderElements({"bandwidth", "time", "speedup"}) ); - writeTableRow( performer, RowElements({ bandwidth, time, speedup }) ); + writeTableHeader( performer, result.getTableHeader() ); + writeTableRow( performer, result.getRowElements() ); return this->baseTime; } - // Recursive template function to deal with multiple computations with the - // same reset function. template< typename ResetFunction, typename ComputeFunction, typename... NextComputations > inline double time( ResetFunction reset, const String & performer, - ComputeFunction & compute, - NextComputations & ... nextComputations ) + ComputeFunction & compute ) { - time( reset, performer, compute ); - time( reset, nextComputations... ); - return this->baseTime; + BenchmarkResult result; + return time( reset, performer, compute, result ); } // Adds an error message to the log. Should be called in places where the @@ -445,6 +470,12 @@ public: using Logging::save; + Solvers::IterativeSolverMonitor< double, int >& + getMonitor() + { + return monitor; + } + protected: int loops; double datasetSize = 0.0; @@ -452,5 +483,49 @@ protected: Solvers::IterativeSolverMonitor< double, int > monitor; }; + +Benchmark::MetadataMap getHardwareMetadata() +{ + const int cpu_id = 0; + Devices::CacheSizes cacheSizes = Devices::SystemInfo::getCPUCacheSizes( cpu_id ); + String cacheInfo = String( cacheSizes.L1data ) + ", " + + String( cacheSizes.L1instruction ) + ", " + + String( cacheSizes.L2 ) + ", " + + String( cacheSizes.L3 ); +#ifdef HAVE_CUDA + const int activeGPU = Devices::CudaDeviceInfo::getActiveDevice(); + const String deviceArch = String( Devices::CudaDeviceInfo::getArchitectureMajor( activeGPU ) ) + "." + + String( Devices::CudaDeviceInfo::getArchitectureMinor( activeGPU ) ); +#endif + Benchmark::MetadataMap metadata { + { "host name", Devices::SystemInfo::getHostname() }, + { "architecture", Devices::SystemInfo::getArchitecture() }, + { "system", Devices::SystemInfo::getSystemName() }, + { "system release", Devices::SystemInfo::getSystemRelease() }, + { "start time", Devices::SystemInfo::getCurrentTime() }, +#ifdef HAVE_MPI + { "number of MPI processes", Communicators::MpiCommunicator::GetSize( Communicators::MpiCommunicator::AllGroup ) }, +#endif + { "OpenMP enabled", Devices::Host::isOMPEnabled() }, + { "OpenMP threads", Devices::Host::getMaxThreadsCount() }, + { "CPU model name", Devices::SystemInfo::getCPUModelName( cpu_id ) }, + { "CPU cores", Devices::SystemInfo::getNumberOfCores( cpu_id ) }, + { "CPU threads per core", Devices::SystemInfo::getNumberOfThreads( cpu_id ) / Devices::SystemInfo::getNumberOfCores( cpu_id ) }, + { "CPU max frequency (MHz)", Devices::SystemInfo::getCPUMaxFrequency( cpu_id ) / 1e3 }, + { "CPU cache sizes (L1d, L1i, L2, L3) (kiB)", cacheInfo }, +#ifdef HAVE_CUDA + { "GPU name", Devices::CudaDeviceInfo::getDeviceName( activeGPU ) }, + { "GPU architecture", deviceArch }, + { "GPU CUDA cores", Devices::CudaDeviceInfo::getCudaCores( activeGPU ) }, + { "GPU clock rate (MHz)", (double) Devices::CudaDeviceInfo::getClockRate( activeGPU ) / 1e3 }, + { "GPU global memory (GB)", (double) Devices::CudaDeviceInfo::getGlobalMemory( activeGPU ) / 1e9 }, + { "GPU memory clock rate (MHz)", (double) Devices::CudaDeviceInfo::getMemoryClockRate( activeGPU ) / 1e3 }, + { "GPU memory ECC enabled", Devices::CudaDeviceInfo::getECCEnabled( activeGPU ) }, +#endif + }; + + return metadata; +} + } // namespace Benchmarks } // namespace TNL diff --git a/src/Benchmarks/CMakeLists.txt b/src/Benchmarks/CMakeLists.txt index e34ade5be..e0637205f 100644 --- a/src/Benchmarks/CMakeLists.txt +++ b/src/Benchmarks/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory( HeatEquation ) add_subdirectory( BLAS ) add_subdirectory( SpMV ) +add_subdirectory( DistSpMV ) add_subdirectory( LinearSolvers ) set( headers diff --git a/src/Benchmarks/DistSpMV/CMakeLists.txt b/src/Benchmarks/DistSpMV/CMakeLists.txt new file mode 100644 index 000000000..57ccdd7a9 --- /dev/null +++ b/src/Benchmarks/DistSpMV/CMakeLists.txt @@ -0,0 +1,11 @@ +if( BUILD_CUDA ) + cuda_add_executable( tnl-benchmark-distributed-spmv-cuda tnl-benchmark-distributed-spmv.cu ) + target_link_libraries( tnl-benchmark-distributed-spmv-cuda tnl ) + + install( TARGETS tnl-benchmark-distributed-spmv-cuda RUNTIME DESTINATION bin ) +endif() + +add_executable( tnl-benchmark-distributed-spmv tnl-benchmark-distributed-spmv.cpp ) +target_link_libraries( tnl-benchmark-distributed-spmv tnl ) + +install( TARGETS tnl-benchmark-distributed-spmv RUNTIME DESTINATION bin ) diff --git a/src/Benchmarks/DistSpMV/ordering.h b/src/Benchmarks/DistSpMV/ordering.h new file mode 100644 index 000000000..141c17996 --- /dev/null +++ b/src/Benchmarks/DistSpMV/ordering.h @@ -0,0 +1,21 @@ +#pragma once + +template< typename Matrix, typename PermutationVector > +void +getTrivialOrdering( const Matrix& matrix, PermutationVector& perm, PermutationVector& iperm ) +{ + using IndexType = typename Matrix::IndexType; + + // allocate permutation vectors + perm.setSize( matrix.getRows() ); + iperm.setSize( matrix.getRows() ); + + const IndexType N = matrix.getRows() / 2; + for( IndexType i = 0; i < N; i++ ) { + perm[ 2 * i ] = i; + perm[ 2 * i + 1 ] = i + N; + iperm[ i ] = 2 * i; + iperm[ i + N ] = 2 * i + 1; + } +} + diff --git a/src/Benchmarks/DistSpMV/tnl-benchmark-distributed-spmv.cpp b/src/Benchmarks/DistSpMV/tnl-benchmark-distributed-spmv.cpp new file mode 100644 index 000000000..63c02eab4 --- /dev/null +++ b/src/Benchmarks/DistSpMV/tnl-benchmark-distributed-spmv.cpp @@ -0,0 +1,11 @@ +/*************************************************************************** + tnl-benchmark-distributed-spmv.cpp - description + ------------------- + begin : Sep 11, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#include "tnl-benchmark-distributed-spmv.h" diff --git a/src/Benchmarks/DistSpMV/tnl-benchmark-distributed-spmv.cu b/src/Benchmarks/DistSpMV/tnl-benchmark-distributed-spmv.cu new file mode 100644 index 000000000..7e9094fbb --- /dev/null +++ b/src/Benchmarks/DistSpMV/tnl-benchmark-distributed-spmv.cu @@ -0,0 +1,11 @@ +/*************************************************************************** + tnl-benchmark-distributed-spmv.cu - description + ------------------- + begin : Sep 11, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#include "tnl-benchmark-distributed-spmv.h" diff --git a/src/Benchmarks/DistSpMV/tnl-benchmark-distributed-spmv.h b/src/Benchmarks/DistSpMV/tnl-benchmark-distributed-spmv.h new file mode 100644 index 000000000..11ae35b43 --- /dev/null +++ b/src/Benchmarks/DistSpMV/tnl-benchmark-distributed-spmv.h @@ -0,0 +1,357 @@ +/*************************************************************************** + tnl-benchmark-distributed-spmv.h - description + ------------------- + begin : Sep 11, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by: Jakub Klinkovsky + +#pragma once + +#ifndef NDEBUG +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../Benchmarks.h" +#include "ordering.h" + +#include + +using namespace TNL; +using namespace TNL::Benchmarks; + +#ifdef HAVE_MPI +using CommunicatorType = Communicators::MpiCommunicator; +#else +using CommunicatorType = Communicators::NoDistrCommunicator; +#endif + + +template< typename Matrix, typename Vector > +void +benchmarkSpmv( Benchmark& benchmark, + const Matrix& matrix, + const Vector& x, + const char* performer = "CPU" ) +{ + Vector y; + y.setLike( x ); + + // reset function + auto reset = [&]() { + y = x; + }; + + // benchmark function + auto compute = [&]() { + matrix.vectorProduct( x, y ); + }; + + benchmark.time( reset, performer, compute ); +} + +template< typename Matrix, typename Vector > +void +benchmarkSpmvCuda( Benchmark& benchmark, + const Matrix& matrix, + const Vector& x ) +{ + using RealType = typename Matrix::RealType; + using IndexType = typename Matrix::IndexType; + using CudaMatrix = typename Matrix::CudaType; + using CudaVector = typename Vector::CudaType; + + CudaVector cuda_x; + cuda_x = x; + + Timer t; + t.start(); + + CudaMatrix cuda_matrix; + cuda_matrix = matrix; + + t.stop(); + std::cout << "--> Copying the matrix to the GPU took " << t.getRealTime() << " seconds." << std::endl; + + benchmarkSpmv( benchmark, cuda_matrix, cuda_x, "GPU" ); +} + +template< typename Matrix, typename Vector > +void +benchmarkDistributedSpmv( Benchmark& benchmark, + // TODO: cannot be const due to internal buffering +// const Matrix& matrix, + Matrix& matrix, + const Vector& x, + const char* performer = "CPU" ) +{ + Vector y; + y.setLike( x ); + + // reset function + auto reset = [&]() { + y = x; + }; + + // benchmark function + auto compute = [&]() { + matrix.vectorProduct( x, y ); + Matrix::CommunicatorType::Barrier( matrix.getCommunicationGroup() ); + }; + + benchmark.time( reset, performer, compute ); +} + +template< typename Matrix, typename Vector > +void +benchmarkDistributedSpmvCuda( Benchmark& benchmark, + const Matrix& matrix, + const Vector& x ) +{ + using RealType = typename Matrix::RealType; + using IndexType = typename Matrix::IndexType; + using CudaMatrix = typename Matrix::CudaType; + using CudaVector = typename Vector::CudaType; + + CudaVector cuda_x; + cuda_x = x; + + Timer t; + t.start(); + + CudaMatrix cuda_matrix; + cuda_matrix = matrix; + + t.stop(); + std::cout << "--> Copying the matrix to the GPU took " << t.getRealTime() << " seconds." << std::endl; + + benchmarkDistributedSpmv( benchmark, cuda_matrix, cuda_x, "GPU" ); +} + +template< typename MatrixType > +struct SpmvBenchmark +{ + using RealType = typename MatrixType::RealType; + using DeviceType = typename MatrixType::DeviceType; + using IndexType = typename MatrixType::IndexType; + using VectorType = Containers::Vector< RealType, DeviceType, IndexType >; + + using Partitioner = DistributedContainers::Partitioner< IndexType, CommunicatorType >; + using DistributedMatrix = DistributedContainers::DistributedMatrix< MatrixType, CommunicatorType >; + using DistributedVector = DistributedContainers::DistributedVector< RealType, DeviceType, IndexType, CommunicatorType >; + using DistributedRowLengths = typename DistributedMatrix::CompressedRowLengthsVector; + + static bool + run( Benchmark& benchmark, + Benchmark::MetadataMap metadata, + const Config::ParameterContainer& parameters ) + { + MatrixType matrix; + VectorType vector; + if( ! matrix.load( parameters.getParameter< String >( "input-matrix" ) ) || + ! vector.load( parameters.getParameter< String >( "input-vector" ) ) ) + return false; + + typename MatrixType::CompressedRowLengthsVector rowLengths; + matrix.getCompressedRowLengths( rowLengths ); + const IndexType maxRowLength = rowLengths.max(); + + const String name = String( (CommunicatorType::isDistributed()) ? "DistSpMV" : "SpMV" ) + + " (" + parameters.getParameter< String >( "name" ) + "): "; + benchmark.newBenchmark( name, metadata ); + benchmark.setMetadataColumns( Benchmark::MetadataColumns({ + // TODO: strip the device +// {"matrix type", matrix.getType()}, + {"rows", matrix.getRows()}, + {"columns", matrix.getColumns()}, + // FIXME: getMaxRowLengths() returns 0 for matrices loaded from file +// {"max elements per row", matrix.getMaxRowLength()}, + {"max elements per row", maxRowLength}, + } )); + + const bool reorder = parameters.getParameter< bool >( "reorder-dofs" ); + if( reorder ) { + using PermutationVector = Containers::Vector< IndexType, DeviceType, IndexType >; + PermutationVector perm, iperm; + getTrivialOrdering( matrix, perm, iperm ); + MatrixType matrix_perm; + Matrices::reorderSparseMatrix( matrix, matrix_perm, perm, iperm ); + if( CommunicatorType::isDistributed() ) + runDistributed( benchmark, metadata, parameters, matrix_perm, vector ); + else + runNonDistributed( benchmark, metadata, parameters, matrix_perm, vector ); + } + else { + if( CommunicatorType::isDistributed() ) + runDistributed( benchmark, metadata, parameters, matrix, vector ); + else + runNonDistributed( benchmark, metadata, parameters, matrix, vector ); + } + + return true; + } + + static void + runNonDistributed( Benchmark& benchmark, + Benchmark::MetadataMap metadata, + const Config::ParameterContainer& parameters, + MatrixType& matrix, + VectorType& vector ) + { + benchmarkSpmv( benchmark, matrix, vector ); +#ifdef HAVE_CUDA + benchmarkSpmvCuda( benchmark, matrix, vector ); +#endif + } + + static void + runDistributed( Benchmark& benchmark, + Benchmark::MetadataMap metadata, + const Config::ParameterContainer& parameters, + MatrixType& matrix, + VectorType& vector ) + { + // set up the distributed matrix + const auto group = CommunicatorType::AllGroup; + const auto localRange = Partitioner::splitRange( matrix.getRows(), group ); + DistributedMatrix distributedMatrix( localRange, matrix.getRows(), matrix.getColumns(), group ); + DistributedVector distributedVector( localRange, matrix.getRows(), group ); + + // copy the row lengths from the global matrix to the distributed matrix + DistributedRowLengths distributedRowLengths( localRange, matrix.getRows(), group ); + for( IndexType i = 0; i < distributedMatrix.getLocalMatrix().getRows(); i++ ) { + const auto gi = distributedMatrix.getLocalRowRange().getGlobalIndex( i ); + distributedRowLengths[ gi ] = matrix.getRowLength( gi ); + } + distributedMatrix.setCompressedRowLengths( distributedRowLengths ); + + // copy data from the global matrix/vector into the distributed matrix/vector + for( IndexType i = 0; i < distributedMatrix.getLocalMatrix().getRows(); i++ ) { + const auto gi = distributedMatrix.getLocalRowRange().getGlobalIndex( i ); + distributedVector[ gi ] = vector[ gi ]; + + const IndexType rowLength = matrix.getRowLength( i ); + IndexType columns[ rowLength ]; + RealType values[ rowLength ]; + matrix.getRowFast( gi, columns, values ); + distributedMatrix.setRowFast( gi, columns, values, rowLength ); + } + + benchmarkDistributedSpmv( benchmark, distributedMatrix, distributedVector ); +#ifdef HAVE_CUDA + benchmarkDistributedSpmvCuda( benchmark, distributedMatrix, distributedVector ); +#endif + +#ifndef NDEBUG + // compare results of normal and distributed spmv + VectorType y; + y.setLike( vector ); + matrix.vectorProduct( vector, y ); + DistributedVector distributedY; + distributedY.setLike( distributedVector ); + distributedMatrix.vectorProduct( distributedVector, distributedY ); + const int rank = CommunicatorType::GetRank( distributedMatrix.getCommunicationGroup() ); + const int nproc = CommunicatorType::GetSize( distributedMatrix.getCommunicationGroup() ); + VectorType subY( y, + Partitioner::getOffset( matrix.getRows(), rank, nproc ), + Partitioner::getSizeForRank( matrix.getRows(), rank, nproc ) ); + TNL_ASSERT_EQ( distributedY.getLocalVectorView(), subY, "WRONG RESULT !!!" ); +#endif + } +}; + +void +configSetup( Config::ConfigDescription & config ) +{ + config.addDelimiter( "Benchmark settings:" ); + config.addEntry< String >( "log-file", "Log file name.", "tnl-benchmark-distributed-spmv.log"); + config.addEntry< String >( "output-mode", "Mode for opening the log file.", "overwrite" ); + config.addEntryEnum( "append" ); + config.addEntryEnum( "overwrite" ); + config.addEntry< int >( "loops", "Number of repetitions of the benchmark.", 10 ); + config.addRequiredEntry< String >( "input-matrix", "File name of the input matrix (in binary TNL format)." ); + config.addRequiredEntry< String >( "input-vector", "File name of the input vector (in binary TNL format)." ); + config.addEntry< String >( "name", "Name of the matrix in the benchmark.", "" ); + config.addEntry< int >( "verbose", "Verbose mode.", 1 ); + config.addEntry< bool >( "reorder-dofs", "Reorder matrix entries corresponding to the same DOF together.", false ); + + config.addDelimiter( "Device settings:" ); + Devices::Host::configSetup( config ); + Devices::Cuda::configSetup( config ); + CommunicatorType::configSetup( config ); +} + +int +main( int argc, char* argv[] ) +{ +#ifndef NDEBUG + Debugging::trackFloatingPointExceptions(); +#endif + + Config::ParameterContainer parameters; + Config::ConfigDescription conf_desc; + + configSetup( conf_desc ); + + Communicators::ScopedInitializer< CommunicatorType > scopedInit(argc, argv); + const int rank = CommunicatorType::GetRank( CommunicatorType::AllGroup ); + + if( ! parseCommandLine( argc, argv, conf_desc, parameters ) ) { + conf_desc.printUsage( argv[ 0 ] ); + return EXIT_FAILURE; + } + + if( ! Devices::Host::setup( parameters ) || + ! Devices::Cuda::setup( parameters ) || + ! CommunicatorType::setup( parameters ) ) + return EXIT_FAILURE; + + const String & logFileName = parameters.getParameter< String >( "log-file" ); + const String & outputMode = parameters.getParameter< String >( "output-mode" ); + const unsigned loops = parameters.getParameter< unsigned >( "loops" ); + const unsigned verbose = (rank == 0) ? parameters.getParameter< unsigned >( "verbose" ) : 0; + + // open log file + auto mode = std::ios::out; + if( outputMode == "append" ) + mode |= std::ios::app; + std::ofstream logFile; + if( rank == 0 ) + logFile.open( logFileName.getString(), mode ); + + // init benchmark and common metadata + Benchmark benchmark( loops, verbose ); + + // prepare global metadata + Benchmark::MetadataMap metadata = getHardwareMetadata(); + + // TODO: implement resolveMatrixType +// return ! Matrices::resolveMatrixType< MainConfig, +// Devices::Host, +// SpmvBenchmark >( benchmark, metadata, parameters ); + using MatrixType = Matrices::SlicedEllpack< double, Devices::Host, int >; + const bool status = SpmvBenchmark< MatrixType >::run( benchmark, metadata, parameters ); + + if( rank == 0 ) + if( ! benchmark.save( logFile ) ) { + std::cerr << "Failed to write the benchmark results to file '" << parameters.getParameter< String >( "log-file" ) << "'." << std::endl; + return EXIT_FAILURE; + } + + return ! status; +} diff --git a/src/Benchmarks/LinearSolvers/CMakeLists.txt b/src/Benchmarks/LinearSolvers/CMakeLists.txt index 1a95c92f7..af0187928 100644 --- a/src/Benchmarks/LinearSolvers/CMakeLists.txt +++ b/src/Benchmarks/LinearSolvers/CMakeLists.txt @@ -1,9 +1,12 @@ if( BUILD_CUDA ) - CUDA_ADD_EXECUTABLE( tnl-benchmark-linear-solvers tnl-benchmark-linear-solvers.cu ) - TARGET_LINK_LIBRARIES( tnl-benchmark-linear-solvers tnl ) -else() - ADD_EXECUTABLE( tnl-benchmark-linear-solvers tnl-benchmark-linear-solvers.cpp ) - TARGET_LINK_LIBRARIES( tnl-benchmark-linear-solvers tnl ) + CUDA_ADD_EXECUTABLE( tnl-benchmark-linear-solvers-cuda tnl-benchmark-linear-solvers.cu + OPTIONS -DHAVE_CUSPARSE ) + TARGET_LINK_LIBRARIES( tnl-benchmark-linear-solvers-cuda tnl ${CUDA_cusparse_LIBRARY} ) + + install( TARGETS tnl-benchmark-linear-solvers-cuda RUNTIME DESTINATION bin ) endif() +ADD_EXECUTABLE( tnl-benchmark-linear-solvers tnl-benchmark-linear-solvers.cpp ) +TARGET_LINK_LIBRARIES( tnl-benchmark-linear-solvers tnl ) + install( TARGETS tnl-benchmark-linear-solvers RUNTIME DESTINATION bin ) diff --git a/src/Benchmarks/LinearSolvers/CuSolverWrapper.h b/src/Benchmarks/LinearSolvers/CuSolverWrapper.h new file mode 100644 index 000000000..40b827ef9 --- /dev/null +++ b/src/Benchmarks/LinearSolvers/CuSolverWrapper.h @@ -0,0 +1,135 @@ +#pragma once + +#ifdef HAVE_CUDA + +#include + +#include +#include +#include + + +template< typename Matrix > +struct is_csr_matrix +{ + static constexpr bool value = false; +}; + +template< typename Real, typename Device, typename Index > +struct is_csr_matrix< TNL::Matrices::CSR< Real, Device, Index > > +{ + static constexpr bool value = true; +}; + + +namespace TNL { +namespace Solvers { +namespace Linear { + +template< typename Matrix > +class CuSolverWrapper + : public LinearSolver< Matrix > +{ + static_assert( ::is_csr_matrix< Matrix >::value, "The CuSolverWrapper solver is available only for CSR matrices." ); + static_assert( std::is_same< typename Matrix::DeviceType, Devices::Cuda >::value, "CuSolverWrapper is available only on CUDA" ); + static_assert( std::is_same< typename Matrix::RealType, float >::value || + std::is_same< typename Matrix::RealType, double >::value, "unsupported RealType" ); + static_assert( std::is_same< typename Matrix::IndexType, int >::value, "unsupported IndexType" ); + + using Base = LinearSolver< Matrices::CSR< double, Devices::Cuda, int > >; +public: + using RealType = typename Base::RealType; + using DeviceType = typename Base::DeviceType; + using IndexType = typename Base::IndexType; + using VectorViewType = typename Base::VectorViewType; + using ConstVectorViewType = typename Base::ConstVectorViewType; + + bool solve( ConstVectorViewType b, VectorViewType x ) override + { + TNL_ASSERT_EQ( this->matrix->getRows(), this->matrix->getColumns(), "matrix must be square" ); + TNL_ASSERT_EQ( this->matrix->getColumns(), x.getSize(), "wrong size of the solution vector" ); + TNL_ASSERT_EQ( this->matrix->getColumns(), b.getSize(), "wrong size of the right hand side" ); + + const IndexType size = this->matrix->getRows(); + + this->resetIterations(); + this->setResidue( this->getConvergenceResidue() + 1.0 ); + + cusolverSpHandle_t handle; + cusolverStatus_t status; + cusparseStatus_t cusparse_status; + cusparseMatDescr_t mat_descr; + + status = cusolverSpCreate( &handle ); + if( status != CUSOLVER_STATUS_SUCCESS ) { + std::cerr << "cusolverSpCreate failed: " << status << std::endl; + return false; + } + + cusparse_status = cusparseCreateMatDescr( &mat_descr ); + if( cusparse_status != CUSPARSE_STATUS_SUCCESS ) { + std::cerr << "cusparseCreateMatDescr failed: " << cusparse_status << std::endl; + return false; + } + + cusparseSetMatType( mat_descr, CUSPARSE_MATRIX_TYPE_GENERAL ); + cusparseSetMatIndexBase( mat_descr, CUSPARSE_INDEX_BASE_ZERO ); + + const RealType tol = 1e-16; + const int reorder = 0; + int singularity = 0; + + if( std::is_same< typename Matrix::RealType, float >::value ) + { + status = cusolverSpScsrlsvqr( handle, + size, + this->matrix->getValues().getSize(), + mat_descr, + (const float*) this->matrix->getValues().getData(), + this->matrix->getRowPointers().getData(), + this->matrix->getColumnIndexes().getData(), + (const float*) b.getData(), + tol, + reorder, + (float*) x.getData(), + &singularity ); + + if( status != CUSOLVER_STATUS_SUCCESS ) { + std::cerr << "cusolverSpScsrlsvqr failed: " << status << std::endl; + return false; + } + } + + if( std::is_same< typename Matrix::RealType, double >::value ) + { + status = cusolverSpDcsrlsvqr( handle, + size, + this->matrix->getValues().getSize(), + mat_descr, + (const double*) this->matrix->getValues().getData(), + this->matrix->getRowPointers().getData(), + this->matrix->getColumnIndexes().getData(), + (const double*) b.getData(), + tol, + reorder, + (double*) x.getData(), + &singularity ); + + if( status != CUSOLVER_STATUS_SUCCESS ) { + std::cerr << "cusolverSpDcsrlsvqr failed: " << status << std::endl; + return false; + } + } + + cusparseDestroyMatDescr( mat_descr ); + cusolverSpDestroy( handle ); + + return true; + } +}; + +} // namespace Linear +} // namespace Solvers +} // namespace TNL + +#endif diff --git a/src/Benchmarks/LinearSolvers/benchmarks.h b/src/Benchmarks/LinearSolvers/benchmarks.h new file mode 100644 index 000000000..032ed74ed --- /dev/null +++ b/src/Benchmarks/LinearSolvers/benchmarks.h @@ -0,0 +1,215 @@ +#pragma once + +#include +#include +#include +#include + +#include "../Benchmarks.h" + +#ifdef HAVE_ARMADILLO +#include +#include +#endif + +#include // std::runtime_error + +using namespace TNL; +using namespace TNL::Pointers; +using namespace TNL::Benchmarks; + + +template< typename Device > +const char* +getPerformer() +{ + if( std::is_same< Device, Devices::Cuda >::value ) + return "GPU"; + return "CPU"; +} + +template< typename Matrix > +void barrier( const Matrix& matrix ) +{ +} + +template< typename Matrix, typename Communicator > +void barrier( const DistributedContainers::DistributedMatrix< Matrix, Communicator >& matrix ) +{ + Communicator::Barrier( matrix.getCommunicationGroup() ); +} + +template< template class Preconditioner, typename Matrix > +void +benchmarkPreconditionerUpdate( Benchmark& benchmark, + const Config::ParameterContainer& parameters, + const SharedPointer< Matrix >& matrix ) +{ + barrier( matrix ); + const char* performer = getPerformer< typename Matrix::DeviceType >(); + Preconditioner< Matrix > preconditioner; + preconditioner.setup( parameters ); + + auto reset = []() {}; + auto compute = [&]() { + preconditioner.update( matrix ); + barrier( matrix ); + }; + + benchmark.time( reset, performer, compute ); +} + +template< template class Solver, template class Preconditioner, typename Matrix, typename Vector > +void +benchmarkSolver( Benchmark& benchmark, + const Config::ParameterContainer& parameters, + const SharedPointer< Matrix >& matrix, + const Vector& x0, + const Vector& b ) +{ + barrier( matrix ); + const char* performer = getPerformer< typename Matrix::DeviceType >(); + + // setup + Solver< Matrix > solver; + solver.setup( parameters ); + solver.setMatrix( matrix ); + + // FIXME: getMonitor returns solver monitor specialized for double and int + solver.setSolverMonitor( benchmark.getMonitor() ); + + auto pre = std::make_shared< Preconditioner< Matrix > >(); + pre->setup( parameters ); + solver.setPreconditioner( pre ); + // preconditioner update may throw if it's not implemented for CUDA + try { + pre->update( matrix ); + } + catch ( const std::runtime_error& ) {} + + Vector x; + x.setLike( x0 ); + + // reset function + auto reset = [&]() { + x = x0; + }; + + // benchmark function + auto compute = [&]() { + const bool converged = solver.solve( b, x ); + barrier( matrix ); + if( ! converged ) + throw std::runtime_error("solver did not converge"); + }; + + // subclass BenchmarkResult to add extra columns to the benchmark + // (iterations, preconditioned residue, true residue) + struct MyBenchmarkResult : public BenchmarkResult + { + using HeaderElements = BenchmarkResult::HeaderElements; + using RowElements = BenchmarkResult::RowElements; + + Solver< Matrix >& solver; + const SharedPointer< Matrix >& matrix; + const Vector& x; + const Vector& b; + + MyBenchmarkResult( Solver< Matrix >& solver, + const SharedPointer< Matrix >& matrix, + const Vector& x, + const Vector& b ) + : solver(solver), matrix(matrix), x(x), b(b) + {} + + virtual HeaderElements getTableHeader() const override + { + return HeaderElements({"time", "speedup", "converged", "iterations", "residue_precond", "residue_true"}); + } + + virtual RowElements getRowElements() const override + { + const bool converged = ! std::isnan(solver.getResidue()) && solver.getResidue() < solver.getConvergenceResidue(); + const long iterations = solver.getIterations(); + const double residue_precond = solver.getResidue(); + + Vector r; + r.setLike( x ); + matrix->vectorProduct( x, r ); + r.addVector( b, 1.0, -1.0 ); + const double residue_true = r.lpNorm( 2.0 ) / b.lpNorm( 2.0 ); + + return RowElements({ time, speedup, (double) converged, (double) iterations, + residue_precond, residue_true }); + } + }; + MyBenchmarkResult benchmarkResult( solver, matrix, x, b ); + + benchmark.time( reset, performer, compute, benchmarkResult ); +} + +#ifdef HAVE_ARMADILLO +// TODO: make a TNL solver like UmfpackWrapper +template< typename Vector > +void +benchmarkArmadillo( const Config::ParameterContainer& parameters, + const Pointers::SharedPointer< Matrices::CSR< double, Devices::Host, int > >& matrix, + const Vector& x0, + const Vector& b ) +{ + // copy matrix into Armadillo's class + // sp_mat is in CSC format + arma::uvec _colptr( matrix->getRowPointers().getSize() ); + for( int i = 0; i < matrix->getRowPointers().getSize(); i++ ) + _colptr[ i ] = matrix->getRowPointers()[ i ]; + arma::uvec _rowind( matrix->getColumnIndexes().getSize() ); + for( int i = 0; i < matrix->getColumnIndexes().getSize(); i++ ) + _rowind[ i ] = matrix->getColumnIndexes()[ i ]; + arma::vec _values( matrix->getValues().getData(), matrix->getValues().getSize() ); + arma::sp_mat AT( _rowind, + _colptr, + _values, + matrix->getColumns(), + matrix->getRows() ); + arma::sp_mat A = AT.t(); + + Vector x; + x.setLike( x0 ); + + // Armadillo vector using the same memory as x (with copy_aux_mem=false, strict=true) + arma::vec arma_x( x.getData(), x.getSize(), false, true ); + arma::vec arma_b( b.getData(), b.getSize() ); + + arma::superlu_opts settings; +// settings.equilibrate = false; + settings.equilibrate = true; + settings.pivot_thresh = 1.0; +// settings.permutation = arma::superlu_opts::COLAMD; + settings.permutation = arma::superlu_opts::MMD_AT_PLUS_A; +// settings.refine = arma::superlu_opts::REF_DOUBLE; + settings.refine = arma::superlu_opts::REF_NONE; + + // reset function + auto reset = [&]() { + x = x0; + }; + + // benchmark function + auto compute = [&]() { + const bool converged = arma::spsolve( arma_x, A, arma_b, "superlu", settings ); + if( ! converged ) + throw std::runtime_error("solver did not converge"); + }; + + const int loops = parameters.getParameter< int >( "loops" ); + double time = timeFunction( compute, reset, loops ); + + arma::vec r = A * arma_x - arma_b; +// std::cout << "Converged: " << (time > 0) << ", residue = " << arma::norm( r ) / arma::norm( arma_b ) << " " << std::endl; +// std::cout << "Mean time: " << time / loops << " seconds." << std::endl; + std::cout << "Converged: " << std::setw( 5) << std::boolalpha << (time > 0) << " " + << "iterations = " << std::setw( 4) << "N/A" << " " + << "residue = " << std::setw(10) << arma::norm( r ) / arma::norm( arma_b ) << " " + << "mean time = " << std::setw( 9) << time / loops << " seconds." << std::endl; +} +#endif diff --git a/src/Benchmarks/LinearSolvers/tnl-benchmark-linear-solvers.cpp b/src/Benchmarks/LinearSolvers/tnl-benchmark-linear-solvers.cpp index 917636d6b..f335b4f06 100644 --- a/src/Benchmarks/LinearSolvers/tnl-benchmark-linear-solvers.cpp +++ b/src/Benchmarks/LinearSolvers/tnl-benchmark-linear-solvers.cpp @@ -1,11 +1 @@ -/*************************************************************************** - tnl-benchmark-linear-solvers.cpp - description - ------------------- - begin : Jun 22, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - #include "tnl-benchmark-linear-solvers.h" diff --git a/src/Benchmarks/LinearSolvers/tnl-benchmark-linear-solvers.cu b/src/Benchmarks/LinearSolvers/tnl-benchmark-linear-solvers.cu index 2a117204e..f335b4f06 100644 --- a/src/Benchmarks/LinearSolvers/tnl-benchmark-linear-solvers.cu +++ b/src/Benchmarks/LinearSolvers/tnl-benchmark-linear-solvers.cu @@ -1,11 +1 @@ -/*************************************************************************** - tnl-benchmark-linear-solvers.cu - description - ------------------- - begin : Jun 22, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - #include "tnl-benchmark-linear-solvers.h" diff --git a/src/Benchmarks/LinearSolvers/tnl-benchmark-linear-solvers.h b/src/Benchmarks/LinearSolvers/tnl-benchmark-linear-solvers.h index 3e50f973e..555e6bd3b 100644 --- a/src/Benchmarks/LinearSolvers/tnl-benchmark-linear-solvers.h +++ b/src/Benchmarks/LinearSolvers/tnl-benchmark-linear-solvers.h @@ -1,227 +1,574 @@ /*************************************************************************** tnl-benchmark-linear-solvers.h - description ------------------- - begin : Jun 22, 2014 - copyright : (C) 2014 by Tomas Oberhuber + begin : Sep 18, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ /* See Copyright Notice in tnl/Copyright */ -#ifndef TNL_BENCHMARK_LINEAR_SOLVERS_H_ -#define TNL_BENCHMARK_LINEAR_SOLVERS_H_ +// Implemented by: Jakub Klinkovsky -#include -#include -#include +#pragma once + +#include +#include +#include + +#ifndef NDEBUG +#include +#endif #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include -#include #include -#include +#include +#include +#include + +#include "../Benchmarks.h" +#include "../DistSpMV/ordering.h" +#include "benchmarks.h" + +// FIXME: nvcc 8.0 fails when cusolverSp.h is included (works fine with clang): +// /opt/cuda/include/cuda_fp16.h(3068): error: more than one instance of overloaded function "isinf" matches the argument list: +// function "isinf(float)" +// function "std::isinf(float)" +// argument types are: (float) +#if defined(HAVE_CUDA) && !defined(__NVCC__) + #include "CuSolverWrapper.h" + #define HAVE_CUSOLVER +#endif -using namespace TNL; -using namespace TNL::Matrices; +#include -void configSetup( Config::ConfigDescription& config ) +using namespace TNL; +using namespace TNL::Benchmarks; +using namespace TNL::Pointers; + +#ifdef HAVE_MPI +using CommunicatorType = Communicators::MpiCommunicator; +#else +using CommunicatorType = Communicators::NoDistrCommunicator; +#endif + + +static const std::set< std::string > valid_solvers = { + "gmres", + "cwygmres", + "tfqmr", + "bicgstab", + "bicgstab-ell", +}; + +static const std::set< std::string > valid_preconditioners = { + "jacobi", + "ilu0", + "ilut", +}; + +std::set< std::string > +parse_comma_list( const Config::ParameterContainer& parameters, + const char* parameter, + const std::set< std::string >& options ) { - config.addDelimiter ( "General settings:" ); - config.addRequiredEntry< String >( "test" , "Test to be performed." ); - config.addEntryEnum< String >( "mtx" ); - config.addEntryEnum< String >( "tnl" ); - config.addRequiredEntry< String >( "input-file" , "Input binary file name." ); - config.addEntry< String >( "log-file", "Log file name.", "tnl-benchmark-linear-solvers.log"); - config.addEntry< String >( "precision", "Precision of the arithmetics.", "double" ); - config.addEntry< String >( "matrix-format", "Matrix format.", "csr" ); - config.addEntryEnum< String >( "dense" ); - config.addEntryEnum< String >( "tridiagonal" ); - config.addEntryEnum< String >( "multidiagonal" ); - config.addEntryEnum< String >( "ellpack" ); - config.addEntryEnum< String >( "sliced-ellpack" ); - config.addEntryEnum< String >( "chunked-ellpack" ); - config.addEntryEnum< String >( "csr" ); - config.addEntry< String >( "solver", "Linear solver.", "gmres" ); - config.addEntryEnum< String >( "sor" ); - config.addEntryEnum< String >( "cg" ); - config.addEntryEnum< String >( "gmres" ); - config.addEntry< String >( "device", "Device.", "host" ); - config.addEntryEnum< String >( "host" ); - config.addEntryEnum< String >( "cuda" ); - config.addEntry< int >( "verbose", "Verbose mode.", 1 ); -} + const String solvers = parameters.getParameter< String >( parameter ); -template< typename Solver > -bool benchmarkSolver( const Config::ParameterContainer& parameters, - Pointers::SharedPointer< typename Solver::MatrixType >& matrix) -{ - typedef typename Solver::MatrixType MatrixType; - typedef typename MatrixType::RealType RealType; - typedef typename MatrixType::DeviceType DeviceType; - typedef typename MatrixType::IndexType IndexType; - typedef Containers::Vector< RealType, DeviceType, IndexType > VectorType; - typedef Pointers::SharedPointer< MatrixType > MatrixPointer; - - VectorType x, y, b; - x.setSize( matrix->getColumns() ); - x.setValue( 1.0 / ( RealType ) matrix->getColumns() ); - y.setSize( matrix->getColumns() ); - b.setSize( matrix->getRows() ); - matrix->vectorProduct( x, b ); - - Solver solver; - Solvers::IterativeSolverMonitor< RealType, IndexType > monitor; - monitor.setVerbose( 1 ); - solver.setSolverMonitor( monitor ); - solver.setMatrix( matrix ); - solver.setConvergenceResidue( 1.0e-6 ); - solver.solve( b, y ); - std::cout << std::endl; - return true; + if( solvers == "all" ) + return options; + + std::stringstream ss( solvers.getString() ); + std::string s; + std::set< std::string > set; + + while( std::getline( ss, s, ',' ) ) { + if( ! options.count( s ) ) + throw std::logic_error( std::string("Invalid value in the comma-separated list for the parameter '") + + parameter + "': '" + s + "'. The list contains: '" + solvers.getString() + "'." ); + + set.insert( s ); + + if( ss.peek() == ',' ) + ss.ignore(); + } + + return set; } -template< typename Matrix > -bool readMatrix( const Config::ParameterContainer& parameters, - Matrix& matrix ) +template< typename Matrix, typename Vector > +void +benchmarkIterativeSolvers( Benchmark& benchmark, +// FIXME: ParameterContainer should be copyable, but that leads to double-free +// Config::ParameterContainer parameters, + Config::ParameterContainer& parameters, + const SharedPointer< Matrix >& matrixPointer, + const Vector& x0, + const Vector& b ) { - const String fileName = parameters.getParameter< String >( "input-file" ); +#ifdef HAVE_CUDA + using CudaMatrix = typename Matrix::CudaType; + using CudaVector = typename Vector::CudaType; + + CudaVector cuda_x0, cuda_b; + cuda_x0 = x0; + cuda_b = b; + + SharedPointer< CudaMatrix > cudaMatrixPointer; + *cudaMatrixPointer = *matrixPointer; + + // synchronize shared pointers + Devices::Cuda::synchronizeDevice(); +#endif + + using namespace Solvers::Linear; + using namespace Solvers::Linear::Preconditioners; + + const int ell_max = 2; + const std::set< std::string > solvers = parse_comma_list( parameters, "solvers", valid_solvers ); + const std::set< std::string > preconditioners = parse_comma_list( parameters, "preconditioners", valid_preconditioners ); + const bool with_preconditioner_update = parameters.getParameter< bool >( "with-preconditioner-update" ); + + if( preconditioners.count( "jacobi" ) ) { + if( with_preconditioner_update ) { + benchmark.setOperation("preconditioner update (Jacobi)"); + benchmarkPreconditionerUpdate< Diagonal >( benchmark, parameters, matrixPointer ); + #ifdef HAVE_CUDA + benchmarkPreconditionerUpdate< Diagonal >( benchmark, parameters, cudaMatrixPointer ); + #endif + } - Matrix* hostMatrix; - if( std::is_same< typename Matrix::DeviceType, Devices::Cuda >::value ) - { + if( solvers.count( "gmres" ) ) { + benchmark.setOperation("GMRES (Jacobi)"); + parameters.template setParameter< String >( "gmres-variant", "MGSR" ); + benchmarkSolver< GMRES, Diagonal >( benchmark, parameters, matrixPointer, x0, b ); + #ifdef HAVE_CUDA + benchmarkSolver< GMRES, Diagonal >( benchmark, parameters, cudaMatrixPointer, cuda_x0, cuda_b ); + #endif + } - } - if( std::is_same< typename Matrix::DeviceType, Devices::Host >::value ) - { - hostMatrix = &matrix; - try - { - if( ! MatrixReader< Matrix >::readMtxFile( fileName, *hostMatrix ) ) - { - std::cerr << "I am not able to read the matrix file " << fileName << "." << std::endl; - /*logFile << std::endl; - logFile << inputFileName << std::endl; - logFile << "Benchmark failed: Unable to read the matrix." << std::endl;*/ - return false; - } + if( solvers.count( "cwygmres" ) ) { + benchmark.setOperation("CWYGMRES (Jacobi)"); + parameters.template setParameter< String >( "gmres-variant", "CWY" ); + benchmarkSolver< GMRES, Diagonal >( benchmark, parameters, matrixPointer, x0, b ); + #ifdef HAVE_CUDA + benchmarkSolver< GMRES, Diagonal >( benchmark, parameters, cudaMatrixPointer, cuda_x0, cuda_b ); + #endif } - catch( std::bad_alloc ) - { - std::cerr << "Not enough memory to read the matrix." << std::endl; - /*logFile << std::endl; - logFile << inputFileName << std::endl; - logFile << "Benchmark failed: Not enough memory." << std::endl;*/ - return false; + + if( solvers.count( "tfqmr" ) ) { + benchmark.setOperation("TFQMR (Jacobi)"); + benchmarkSolver< TFQMR, Diagonal >( benchmark, parameters, matrixPointer, x0, b ); + #ifdef HAVE_CUDA + benchmarkSolver< TFQMR, Diagonal >( benchmark, parameters, cudaMatrixPointer, cuda_x0, cuda_b ); + #endif } - } - return true; -} -template< typename Matrix > -bool resolveLinearSolver( const Config::ParameterContainer& parameters ) -{ - const String& solver = parameters.getParameter< String >( "solver" ); - typedef Pointers::SharedPointer< Matrix > MatrixPointer; + if( solvers.count( "bicgstab" ) ) { + benchmark.setOperation("BiCGstab (Jacobi)"); + benchmarkSolver< BICGStab, Diagonal >( benchmark, parameters, matrixPointer, x0, b ); + #ifdef HAVE_CUDA + benchmarkSolver< BICGStab, Diagonal >( benchmark, parameters, cudaMatrixPointer, cuda_x0, cuda_b ); + #endif + } - MatrixPointer matrix; - if( ! readMatrix( parameters, *matrix ) ) - return false; + if( solvers.count( "bicgstab-ell" ) ) { + benchmark.setOperation("BiCGstab (Jacobi)"); + for( int ell = 1; ell <= ell_max; ell++ ) { + parameters.template setParameter< int >( "bicgstab-ell", ell ); + benchmark.setOperation("BiCGstab(" + String(ell) + ") (Jacobi)"); + benchmarkSolver< BICGStabL, Diagonal >( benchmark, parameters, matrixPointer, x0, b ); + #ifdef HAVE_CUDA + benchmarkSolver< BICGStabL, Diagonal >( benchmark, parameters, cudaMatrixPointer, cuda_x0, cuda_b ); + #endif + } + } + } - if( solver == "gmres" ) - return benchmarkSolver< Solvers::Linear::GMRES< Matrix > >( parameters, matrix ); - if( solver == "cg" ) - return benchmarkSolver< Solvers::Linear::CG< Matrix > >( parameters, matrix ); + if( preconditioners.count( "ilu0" ) ) { + if( with_preconditioner_update ) { + benchmark.setOperation("preconditioner update (ILU0)"); + benchmarkPreconditionerUpdate< ILU0 >( benchmark, parameters, matrixPointer ); + #ifdef HAVE_CUDA + benchmarkPreconditionerUpdate< ILU0 >( benchmark, parameters, cudaMatrixPointer ); + #endif + } - if( solver == "bicgstab" ) - return benchmarkSolver< Solvers::Linear::BICGStab< Matrix > >( parameters, matrix ); + if( solvers.count( "gmres" ) ) { + benchmark.setOperation("GMRES (ILU0)"); + parameters.template setParameter< String >( "gmres-variant", "MGSR" ); + benchmarkSolver< GMRES, ILU0 >( benchmark, parameters, matrixPointer, x0, b ); + #ifdef HAVE_CUDA + benchmarkSolver< GMRES, ILU0 >( benchmark, parameters, cudaMatrixPointer, cuda_x0, cuda_b ); + #endif + } - if( solver == "tfqmr" ) - return benchmarkSolver< Solvers::Linear::TFQMR< Matrix > >( parameters, matrix ); + if( solvers.count( "cwygmres" ) ) { + benchmark.setOperation("CWYGMRES (ILU0)"); + parameters.template setParameter< String >( "gmres-variant", "CWY" ); + benchmarkSolver< GMRES, ILU0 >( benchmark, parameters, matrixPointer, x0, b ); + #ifdef HAVE_CUDA + benchmarkSolver< GMRES, ILU0 >( benchmark, parameters, cudaMatrixPointer, cuda_x0, cuda_b ); + #endif + } - std::cerr << "Unknown solver " << solver << "." << std::endl; - return false; -} + if( solvers.count( "tfqmr" ) ) { + benchmark.setOperation("TFQMR (ILU0)"); + benchmarkSolver< TFQMR, ILU0 >( benchmark, parameters, matrixPointer, x0, b ); + #ifdef HAVE_CUDA + benchmarkSolver< TFQMR, ILU0 >( benchmark, parameters, cudaMatrixPointer, cuda_x0, cuda_b ); + #endif + } -template< typename Real, - typename Device > -bool resolveMatrixFormat( const Config::ParameterContainer& parameters ) -{ - const String& matrixFormat = parameters.getParameter< String >( "matrix-format" ); + if( solvers.count( "bicgstab" ) ) { + benchmark.setOperation("BiCGstab (ILU0)"); + benchmarkSolver< BICGStab, ILU0 >( benchmark, parameters, matrixPointer, x0, b ); + #ifdef HAVE_CUDA + benchmarkSolver< BICGStab, ILU0 >( benchmark, parameters, cudaMatrixPointer, cuda_x0, cuda_b ); + #endif + } - if( matrixFormat == "dense" ) - return resolveLinearSolver< Dense< Real, Device, int > >( parameters ); + if( solvers.count( "bicgstab-ell" ) ) { + for( int ell = 1; ell <= ell_max; ell++ ) { + parameters.template setParameter< int >( "bicgstab-ell", ell ); + benchmark.setOperation("BiCGstab(" + String(ell) + ") (ILU0)"); + benchmarkSolver< BICGStabL, ILU0 >( benchmark, parameters, matrixPointer, x0, b ); + #ifdef HAVE_CUDA + benchmarkSolver< BICGStabL, ILU0 >( benchmark, parameters, cudaMatrixPointer, cuda_x0, cuda_b ); + #endif + } + } + } - if( matrixFormat == "tridiagonal" ) - return resolveLinearSolver< Tridiagonal< Real, Device, int > >( parameters ); - if( matrixFormat == "multidiagonal" ) - return resolveLinearSolver< Multidiagonal< Real, Device, int > >( parameters ); + if( preconditioners.count( "ilut" ) ) { + if( with_preconditioner_update ) { + benchmark.setOperation("preconditioner update (ILUT)"); + benchmarkPreconditionerUpdate< ILUT >( benchmark, parameters, matrixPointer ); + #ifdef HAVE_CUDA + benchmarkPreconditionerUpdate< ILUT >( benchmark, parameters, cudaMatrixPointer ); + #endif + } - if( matrixFormat == "ellpack" ) - return resolveLinearSolver< Ellpack< Real, Device, int > >( parameters ); + if( solvers.count( "gmres" ) ) { + benchmark.setOperation("GMRES (ILUT)"); + parameters.template setParameter< String >( "gmres-variant", "MGSR" ); + benchmarkSolver< GMRES, ILUT >( benchmark, parameters, matrixPointer, x0, b ); + #ifdef HAVE_CUDA + benchmarkSolver< GMRES, ILUT >( benchmark, parameters, cudaMatrixPointer, cuda_x0, cuda_b ); + #endif + } - if( matrixFormat == "sliced-ellpack" ) - return resolveLinearSolver< SlicedEllpack< Real, Device, int > >( parameters ); + if( solvers.count( "cwygmres" ) ) { + benchmark.setOperation("CWYGMRES (ILUT)"); + parameters.template setParameter< String >( "gmres-variant", "CWY" ); + benchmarkSolver< GMRES, ILUT >( benchmark, parameters, matrixPointer, x0, b ); + #ifdef HAVE_CUDA + benchmarkSolver< GMRES, ILUT >( benchmark, parameters, cudaMatrixPointer, cuda_x0, cuda_b ); + #endif + } - if( matrixFormat == "chunked-ellpack" ) - return resolveLinearSolver< ChunkedEllpack< Real, Device, int > >( parameters ); + if( solvers.count( "tfqmr" ) ) { + benchmark.setOperation("TFQMR (ILUT)"); + benchmarkSolver< TFQMR, ILUT >( benchmark, parameters, matrixPointer, x0, b ); + #ifdef HAVE_CUDA + benchmarkSolver< TFQMR, ILUT >( benchmark, parameters, cudaMatrixPointer, cuda_x0, cuda_b ); + #endif + } - if( matrixFormat == "csr" ) - return resolveLinearSolver< CSR< Real, Device, int > >( parameters ); + if( solvers.count( "bicgstab" ) ) { + benchmark.setOperation("BiCGstab (ILUT)"); + benchmarkSolver< BICGStab, ILUT >( benchmark, parameters, matrixPointer, x0, b ); + #ifdef HAVE_CUDA + benchmarkSolver< BICGStab, ILUT >( benchmark, parameters, cudaMatrixPointer, cuda_x0, cuda_b ); + #endif + } - std::cerr << "Unknown matrix format " << matrixFormat << "." << std::endl; - return false; + if( solvers.count( "bicgstab-ell" ) ) { + for( int ell = 1; ell <= ell_max; ell++ ) { + parameters.template setParameter< int >( "bicgstab-ell", ell ); + benchmark.setOperation("BiCGstab(" + String(ell) + ") (ILUT)"); + benchmarkSolver< BICGStabL, ILUT >( benchmark, parameters, matrixPointer, x0, b ); + #ifdef HAVE_CUDA + benchmarkSolver< BICGStabL, ILUT >( benchmark, parameters, cudaMatrixPointer, cuda_x0, cuda_b ); + #endif + } + } + } } -template< typename Real > -bool resolveDevice( const Config::ParameterContainer& parameters ) +template< typename MatrixType > +struct LinearSolversBenchmark { - const String& device = parameters.getParameter< String >( "device" ); + using RealType = typename MatrixType::RealType; + using DeviceType = typename MatrixType::DeviceType; + using IndexType = typename MatrixType::IndexType; + using VectorType = Containers::Vector< RealType, DeviceType, IndexType >; + + using Partitioner = DistributedContainers::Partitioner< IndexType, CommunicatorType >; + using DistributedMatrix = DistributedContainers::DistributedMatrix< MatrixType, CommunicatorType >; + using DistributedVector = DistributedContainers::DistributedVector< RealType, DeviceType, IndexType, CommunicatorType >; + using DistributedRowLengths = typename DistributedMatrix::CompressedRowLengthsVector; + + static bool + run( Benchmark& benchmark, + Benchmark::MetadataMap metadata, +// FIXME: ParameterContainer should be copyable, but that leads to double-free +// const Config::ParameterContainer& parameters ) + Config::ParameterContainer& parameters ) + { + SharedPointer< MatrixType > matrixPointer; + VectorType x0, b; + if( ! matrixPointer->load( parameters.getParameter< String >( "input-matrix" ) ) || + ! x0.load( parameters.getParameter< String >( "input-dof" ) ) || + ! b.load( parameters.getParameter< String >( "input-rhs" ) ) ) + return false; + + typename MatrixType::CompressedRowLengthsVector rowLengths; + matrixPointer->getCompressedRowLengths( rowLengths ); + const IndexType maxRowLength = rowLengths.max(); + + const String name = String( (CommunicatorType::isDistributed()) ? "Distributed linear solvers" : "Linear solvers" ) + + " (" + parameters.getParameter< String >( "name" ) + "): "; + benchmark.newBenchmark( name, metadata ); + benchmark.setMetadataColumns( Benchmark::MetadataColumns({ + // TODO: strip the device +// {"matrix type", matrixPointer->getType()}, + {"rows", matrixPointer->getRows()}, + {"columns", matrixPointer->getColumns()}, + // FIXME: getMaxRowLengths() returns 0 for matrices loaded from file +// {"max elements per row", matrixPointer->getMaxRowLength()}, + {"max elements per row", maxRowLength}, + } )); + + const bool reorder = parameters.getParameter< bool >( "reorder-dofs" ); + if( reorder ) { + using PermutationVector = Containers::Vector< IndexType, DeviceType, IndexType >; + PermutationVector perm, iperm; + getTrivialOrdering( *matrixPointer, perm, iperm ); + SharedPointer< MatrixType > matrix_perm; + VectorType x0_perm, b_perm; + x0_perm.setLike( x0 ); + b_perm.setLike( b ); + Matrices::reorderSparseMatrix( *matrixPointer, *matrix_perm, perm, iperm ); + Matrices::reorderArray( x0, x0_perm, perm ); + Matrices::reorderArray( b, b_perm, perm ); + if( CommunicatorType::isDistributed() ) + runDistributed( benchmark, metadata, parameters, matrix_perm, x0_perm, b_perm ); + else + runNonDistributed( benchmark, metadata, parameters, matrix_perm, x0_perm, b_perm ); + } + else { + if( CommunicatorType::isDistributed() ) + runDistributed( benchmark, metadata, parameters, matrixPointer, x0, b ); + else + runNonDistributed( benchmark, metadata, parameters, matrixPointer, x0, b ); + } + + return true; + } + + static void + runDistributed( Benchmark& benchmark, + Benchmark::MetadataMap metadata, +// FIXME: ParameterContainer should be copyable, but that leads to double-free +// const Config::ParameterContainer& parameters, + Config::ParameterContainer& parameters, + const SharedPointer< MatrixType >& matrixPointer, + const VectorType& x0, + const VectorType& b ) + { + // set up the distributed matrix + const auto group = CommunicatorType::AllGroup; + const auto localRange = Partitioner::splitRange( matrixPointer->getRows(), group ); + SharedPointer< DistributedMatrix > distMatrixPointer( localRange, matrixPointer->getRows(), matrixPointer->getColumns(), group ); + DistributedVector dist_x0( localRange, matrixPointer->getRows(), group ); + DistributedVector dist_b( localRange, matrixPointer->getRows(), group ); + + // copy the row lengths from the global matrix to the distributed matrix + DistributedRowLengths distributedRowLengths( localRange, matrixPointer->getRows(), group ); + for( IndexType i = 0; i < distMatrixPointer->getLocalMatrix().getRows(); i++ ) { + const auto gi = distMatrixPointer->getLocalRowRange().getGlobalIndex( i ); + distributedRowLengths[ gi ] = matrixPointer->getRowLength( gi ); + } + distMatrixPointer->setCompressedRowLengths( distributedRowLengths ); + + // copy data from the global matrix/vector into the distributed matrix/vector + for( IndexType i = 0; i < distMatrixPointer->getLocalMatrix().getRows(); i++ ) { + const auto gi = distMatrixPointer->getLocalRowRange().getGlobalIndex( i ); + dist_x0[ gi ] = x0[ gi ]; + dist_b[ gi ] = b[ gi ]; + + const IndexType rowLength = matrixPointer->getRowLength( i ); + IndexType columns[ rowLength ]; + RealType values[ rowLength ]; + matrixPointer->getRowFast( gi, columns, values ); + distMatrixPointer->setRowFast( gi, columns, values, rowLength ); + } - if( device == "host" ) - return resolveMatrixFormat< Real, Devices::Host >( parameters ); + std::cout << "Iterative solvers:" << std::endl; + benchmarkIterativeSolvers( benchmark, parameters, distMatrixPointer, dist_x0, dist_b ); + } + + static void + runNonDistributed( Benchmark& benchmark, + Benchmark::MetadataMap metadata, +// FIXME: ParameterContainer should be copyable, but that leads to double-free +// const Config::ParameterContainer& parameters, + Config::ParameterContainer& parameters, + const SharedPointer< MatrixType >& matrixPointer, + const VectorType& x0, + const VectorType& b ) + { + // direct solvers + if( parameters.getParameter< bool >( "with-direct" ) ) { + using CSR = Matrices::CSR< RealType, DeviceType, IndexType >; + SharedPointer< CSR > matrixCopy; + Matrices::copySparseMatrix( *matrixCopy, *matrixPointer ); + +#ifdef HAVE_UMFPACK + std::cout << "UMFPACK wrapper:" << std::endl; + using UmfpackSolver = Solvers::Linear::UmfpackWrapper< CSR >; + using Preconditioner = Solvers::Linear::Preconditioners::Preconditioner< CSR >; + benchmarkSolver< UmfpackSolver, Preconditioner >( parameters, matrixCopy, x0, b ); +#endif + +#ifdef HAVE_ARMADILLO + std::cout << "Armadillo wrapper (which wraps SuperLU):" << std::endl; + benchmarkArmadillo( parameters, matrixCopy, x0, b ); +#endif + } + + std::cout << "Iterative solvers:" << std::endl; + benchmarkIterativeSolvers( benchmark, parameters, matrixPointer, x0, b ); - if( device == "cuda" ) - return resolveMatrixFormat< Real, Devices::Cuda >( parameters ); +#ifdef HAVE_CUSOLVER + std::cout << "CuSOLVER:" << std::endl; + { + using CSR = Matrices::CSR< RealType, DeviceType, IndexType >; + SharedPointer< CSR > matrixCopy; + Matrices::copySparseMatrix( *matrixCopy, *matrixPointer ); + + SharedPointer< typename CSR::CudaType > cuda_matrixCopy; + *cuda_matrixCopy = *matrixCopy; + typename VectorType::CudaType cuda_x0, cuda_b; + cuda_x0.setLike( x0 ); + cuda_b.setLike( b ); + cuda_x0 = x0; + cuda_b = b; + + using namespace Solvers::Linear; + using namespace Solvers::Linear::Preconditioners; + benchmarkSolver< CuSolverWrapper, Preconditioner >( benchmark, parameters, cuda_matrixCopy, cuda_x0, cuda_b ); + } +#endif + } +}; - std::cerr << "Uknown device " << device << "." << std::endl; - return false; +void +configSetup( Config::ConfigDescription& config ) +{ + config.addDelimiter( "Benchmark settings:" ); + config.addEntry< String >( "log-file", "Log file name.", "tnl-benchmark-linear-solvers.log"); + config.addEntry< String >( "output-mode", "Mode for opening the log file.", "overwrite" ); + config.addEntryEnum( "append" ); + config.addEntryEnum( "overwrite" ); + config.addEntry< int >( "loops", "Number of repetitions of the benchmark.", 10 ); + config.addRequiredEntry< String >( "input-matrix", "File name of the input matrix (in binary TNL format)." ); + config.addRequiredEntry< String >( "input-dof", "File name of the input DOF vector (in binary TNL format)." ); + config.addRequiredEntry< String >( "input-rhs", "File name of the input right-hand-side vector (in binary TNL format)." ); + config.addEntry< String >( "name", "Name of the matrix in the benchmark.", "" ); + config.addEntry< int >( "verbose", "Verbose mode.", 1 ); + config.addEntry< bool >( "reorder-dofs", "Reorder matrix entries corresponding to the same DOF together.", false ); + config.addEntry< bool >( "with-direct", "Includes the 3rd party direct solvers in the benchmark.", false ); + config.addEntry< String >( "solvers", "Comma-separated list of solvers to run benchmarks for. Options: gmres, cwygmres, tfqmr, bicgstab, bicgstab-ell.", "all" ); + config.addEntry< String >( "preconditioners", "Comma-separated list of preconditioners to run benchmarks for. Options: jacobi, ilu0, ilut.", "all" ); + config.addEntry< bool >( "with-preconditioner-update", "Run benchmark for the preconditioner update.", true ); + + config.addDelimiter( "Device settings:" ); + Devices::Host::configSetup( config ); + Devices::Cuda::configSetup( config ); + CommunicatorType::configSetup( config ); + + config.addDelimiter( "Linear solver settings:" ); + Solvers::IterativeSolver< double, int >::configSetup( config ); + using Matrix = Matrices::SlicedEllpack< double, Devices::Host, int >; + using GMRES = Solvers::Linear::GMRES< Matrix >; + GMRES::configSetup( config ); + using BiCGstabL = Solvers::Linear::BICGStabL< Matrix >; + BiCGstabL::configSetup( config ); + using ILUT = Solvers::Linear::Preconditioners::ILUT< Matrix >; + ILUT::configSetup( config ); } -int main( int argc, char* argv[] ) +int +main( int argc, char* argv[] ) { +#ifndef NDEBUG + Debugging::trackFloatingPointExceptions(); +#endif + Config::ParameterContainer parameters; Config::ConfigDescription conf_desc; configSetup( conf_desc ); - - if( ! parseCommandLine( argc, argv, conf_desc, parameters ) ) - { + + Communicators::ScopedInitializer< CommunicatorType > scopedInit(argc, argv); + const int rank = CommunicatorType::GetRank( CommunicatorType::AllGroup ); + + if( ! parseCommandLine( argc, argv, conf_desc, parameters ) ) { conf_desc.printUsage( argv[ 0 ] ); - return 1; + return EXIT_FAILURE; } - const String& precision = parameters.getParameter< String >( "precision" ); - if( precision == "float" ) - if( ! resolveDevice< float >( parameters ) ) + if( ! Devices::Host::setup( parameters ) || + ! Devices::Cuda::setup( parameters ) || + ! CommunicatorType::setup( parameters ) ) + return EXIT_FAILURE; + + const String & logFileName = parameters.getParameter< String >( "log-file" ); + const String & outputMode = parameters.getParameter< String >( "output-mode" ); + const unsigned loops = parameters.getParameter< unsigned >( "loops" ); + const unsigned verbose = (rank == 0) ? parameters.getParameter< unsigned >( "verbose" ) : 0; + + // open log file + auto mode = std::ios::out; + if( outputMode == "append" ) + mode |= std::ios::app; + std::ofstream logFile; + if( rank == 0 ) + logFile.open( logFileName.getString(), mode ); + + // init benchmark and common metadata + Benchmark benchmark( loops, verbose ); + + // prepare global metadata + Benchmark::MetadataMap metadata = getHardwareMetadata(); + + // TODO: implement resolveMatrixType +// return ! Matrices::resolveMatrixType< MainConfig, +// Devices::Host, +// LinearSolversBenchmark >( benchmark, metadata, parameters ); + using MatrixType = Matrices::SlicedEllpack< double, Devices::Host, int >; + const bool status = LinearSolversBenchmark< MatrixType >::run( benchmark, metadata, parameters ); + + if( rank == 0 ) + if( ! benchmark.save( logFile ) ) { + std::cerr << "Failed to write the benchmark results to file '" << parameters.getParameter< String >( "log-file" ) << "'." << std::endl; return EXIT_FAILURE; - if( precision == "double" ) - if( ! resolveDevice< double >( parameters ) ) - return EXIT_FAILURE; - return EXIT_SUCCESS; -} - + } -#endif /* TNL_BENCHMARK_LINEAR_SOLVERS_H_ */ + return ! status; +} diff --git a/src/TNL/Containers/Algorithms/Multireduction_impl.h b/src/TNL/Containers/Algorithms/Multireduction_impl.h index 505c2be0e..580136363 100644 --- a/src/TNL/Containers/Algorithms/Multireduction_impl.h +++ b/src/TNL/Containers/Algorithms/Multireduction_impl.h @@ -179,7 +179,7 @@ reduce( Operation& operation, typedef typename Operation::DataType2 DataType2; typedef typename Operation::ResultType ResultType; - const int block_size = 128; + constexpr int block_size = 128; const int blocks = size / block_size; #ifdef HAVE_OPENMP @@ -194,17 +194,23 @@ reduce( Operation& operation, } // initialize array for thread-local results - ResultType r[ n ]; - for( int k = 0; k < n; k++ ) + // (it is accessed as a row-major matrix with n rows and 4 columns) + ResultType r[ n * 4 ]; + for( int k = 0; k < n * 4; k++ ) r[ k ] = operation.initialValue(); #pragma omp for nowait for( int b = 0; b < blocks; b++ ) { - const int offset = b * block_size; + const IndexType offset = b * block_size; for( int k = 0; k < n; k++ ) { const DataType1* _input1 = input1 + k * ldInput1; - for( IndexType i = 0; i < block_size; i++ ) - operation.firstReduction( r[ k ], offset + i, _input1, input2 ); + ResultType* _r = r + 4 * k; + for( int i = 0; i < block_size; i += 4 ) { + operation.firstReduction( _r[ 0 ], offset + i, _input1, input2 ); + operation.firstReduction( _r[ 1 ], offset + i + 1, _input1, input2 ); + operation.firstReduction( _r[ 2 ], offset + i + 2, _input1, input2 ); + operation.firstReduction( _r[ 3 ], offset + i + 3, _input1, input2 ); + } } } @@ -213,36 +219,88 @@ reduce( Operation& operation, { for( int k = 0; k < n; k++ ) { const DataType1* _input1 = input1 + k * ldInput1; + ResultType* _r = r + 4 * k; for( IndexType i = blocks * block_size; i < size; i++ ) - operation.firstReduction( r[ k ], i, _input1, input2 ); + operation.firstReduction( _r[ 0 ], i, _input1, input2 ); } } + // local reduction of unrolled results + for( int k = 0; k < n; k++ ) { + ResultType* _r = r + 4 * k; + operation.commonReduction( _r[ 0 ], _r[ 1 ] ); + operation.commonReduction( _r[ 0 ], _r[ 2 ] ); + operation.commonReduction( _r[ 0 ], _r[ 3 ] ); + } + // inter-thread reduction of local results #pragma omp critical { for( int k = 0; k < n; k++ ) - operation.commonReduction( result[ k ], r[ k ] ); + operation.commonReduction( result[ k ], r[ 4 * k ] ); } } else { #endif - for( int k = 0; k < n; k++ ) - result[ k ] = operation.initialValue(); + if( blocks > 1 ) { + // initialize array for unrolled results + // (it is accessed as a row-major matrix with n rows and 4 columns) + ResultType r[ n * 4 ]; + for( int k = 0; k < n * 4; k++ ) + r[ k ] = operation.initialValue(); + + // main reduction (explicitly unrolled loop) + for( int b = 0; b < blocks; b++ ) { + const IndexType offset = b * block_size; + for( int k = 0; k < n; k++ ) { + const DataType1* _input1 = input1 + k * ldInput1; + ResultType* _r = r + 4 * k; + for( int i = 0; i < block_size; i += 4 ) { + operation.firstReduction( _r[ 0 ], offset + i, _input1, input2 ); + operation.firstReduction( _r[ 1 ], offset + i + 1, _input1, input2 ); + operation.firstReduction( _r[ 2 ], offset + i + 2, _input1, input2 ); + operation.firstReduction( _r[ 3 ], offset + i + 3, _input1, input2 ); + } + } + } - for( int b = 0; b < blocks; b++ ) { - const int offset = b * block_size; + // reduction of the last, incomplete block (not unrolled) for( int k = 0; k < n; k++ ) { const DataType1* _input1 = input1 + k * ldInput1; - for( IndexType i = 0; i < block_size; i++ ) - operation.firstReduction( result[ k ], offset + i, _input1, input2 ); + ResultType* _r = r + 4 * k; + for( IndexType i = blocks * block_size; i < size; i++ ) + operation.firstReduction( _r[ 0 ], i, _input1, input2 ); + } + + // reduction of unrolled results + for( int k = 0; k < n; k++ ) { + ResultType* _r = r + 4 * k; + operation.commonReduction( _r[ 0 ], _r[ 1 ] ); + operation.commonReduction( _r[ 0 ], _r[ 2 ] ); + operation.commonReduction( _r[ 0 ], _r[ 3 ] ); + + // copy the result into the output parameter + result[ k ] = _r[ 0 ]; } } + else { + for( int k = 0; k < n; k++ ) + result[ k ] = operation.initialValue(); - for( int k = 0; k < n; k++ ) { - const DataType1* _input1 = input1 + k * ldInput1; - for( IndexType i = blocks * block_size; i < size; i++ ) - operation.firstReduction( result[ k ], i, _input1, input2 ); + for( int b = 0; b < blocks; b++ ) { + const IndexType offset = b * block_size; + for( int k = 0; k < n; k++ ) { + const DataType1* _input1 = input1 + k * ldInput1; + for( int i = 0; i < block_size; i++ ) + operation.firstReduction( result[ k ], offset + i, _input1, input2 ); + } + } + + for( int k = 0; k < n; k++ ) { + const DataType1* _input1 = input1 + k * ldInput1; + for( IndexType i = blocks * block_size; i < size; i++ ) + operation.firstReduction( result[ k ], i, _input1, input2 ); + } } #ifdef HAVE_OPENMP } diff --git a/src/TNL/Containers/Algorithms/Reduction_impl.h b/src/TNL/Containers/Algorithms/Reduction_impl.h index ee4e8d979..44769a84c 100644 --- a/src/TNL/Containers/Algorithms/Reduction_impl.h +++ b/src/TNL/Containers/Algorithms/Reduction_impl.h @@ -179,22 +179,22 @@ reduce( Operation& operation, typedef typename Operation::DataType2 DataType2; typedef typename Operation::ResultType ResultType; -#ifdef HAVE_OPENMP constexpr int block_size = 128; + const int blocks = size / block_size; + +#ifdef HAVE_OPENMP if( TNL::Devices::Host::isOMPEnabled() && size >= 2 * block_size ) { // global result variable ResultType result = operation.initialValue(); #pragma omp parallel { - const int blocks = size / block_size; - // initialize array for thread-local results ResultType r[ 4 ] = { operation.initialValue() }; #pragma omp for nowait for( int b = 0; b < blocks; b++ ) { - const int offset = b * block_size; - for( IndexType i = 0; i < block_size; i += 4 ) { + const IndexType offset = b * block_size; + for( int i = 0; i < block_size; i += 4 ) { operation.firstReduction( r[ 0 ], offset + i, input1, input2 ); operation.firstReduction( r[ 1 ], offset + i + 1, input1, input2 ); operation.firstReduction( r[ 2 ], offset + i + 2, input1, input2 ); @@ -209,7 +209,7 @@ reduce( Operation& operation, operation.firstReduction( r[ 0 ], i, input1, input2 ); } - // reduction of local results + // local reduction of unrolled results operation.commonReduction( r[ 0 ], r[ 1 ] ); operation.commonReduction( r[ 0 ], r[ 2 ] ); operation.commonReduction( r[ 0 ], r[ 3 ] ); @@ -224,10 +224,38 @@ reduce( Operation& operation, } else { #endif - ResultType result = operation.initialValue(); - for( IndexType i = 0; i < size; i++ ) - operation.firstReduction( result, i, input1, input2 ); - return result; + if( blocks > 1 ) { + // initialize array for unrolled results + ResultType r[ 4 ] = { operation.initialValue() }; + + // main reduction (explicitly unrolled loop) + for( int b = 0; b < blocks; b++ ) { + const IndexType offset = b * block_size; + for( int i = 0; i < block_size; i += 4 ) { + operation.firstReduction( r[ 0 ], offset + i, input1, input2 ); + operation.firstReduction( r[ 1 ], offset + i + 1, input1, input2 ); + operation.firstReduction( r[ 2 ], offset + i + 2, input1, input2 ); + operation.firstReduction( r[ 3 ], offset + i + 3, input1, input2 ); + } + } + + // reduction of the last, incomplete block (not unrolled) + for( IndexType i = blocks * block_size; i < size; i++ ) + operation.firstReduction( r[ 0 ], i, input1, input2 ); + + // reduction of unrolled results + operation.commonReduction( r[ 0 ], r[ 1 ] ); + operation.commonReduction( r[ 0 ], r[ 2 ] ); + operation.commonReduction( r[ 0 ], r[ 3 ] ); + + return r[ 0 ]; + } + else { + ResultType result = operation.initialValue(); + for( IndexType i = 0; i < size; i++ ) + operation.firstReduction( result, i, input1, input2 ); + return result; + } #ifdef HAVE_OPENMP } #endif diff --git a/src/TNL/DistributedContainers/DistributedArray.h b/src/TNL/DistributedContainers/DistributedArray.h new file mode 100644 index 000000000..0fc7704a4 --- /dev/null +++ b/src/TNL/DistributedContainers/DistributedArray.h @@ -0,0 +1,142 @@ +/*************************************************************************** + DistributedArray.h - description + ------------------- + begin : Sep 6, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by: Jakub Klinkovský + +#pragma once + +#include // std::add_const + +#include +#include +#include +#include + +namespace TNL { +namespace DistributedContainers { + +template< typename Value, + typename Device = Devices::Host, + typename Index = int, + typename Communicator = Communicators::MpiCommunicator > +class DistributedArray +: public Object +{ + using CommunicationGroup = typename Communicator::CommunicationGroup; +public: + using ValueType = Value; + using DeviceType = Device; + using CommunicatorType = Communicator; + using IndexType = Index; + using LocalRangeType = Subrange< Index >; + using LocalArrayType = Containers::Array< Value, Device, Index >; + using LocalArrayViewType = Containers::ArrayView< Value, Device, Index >; + using ConstLocalArrayViewType = Containers::ArrayView< typename std::add_const< Value >::type, Device, Index >; + using HostType = DistributedArray< Value, Devices::Host, Index, Communicator >; + using CudaType = DistributedArray< Value, Devices::Cuda, Index, Communicator >; + + DistributedArray() = default; + + DistributedArray( DistributedArray& ) = default; + + DistributedArray( LocalRangeType localRange, Index globalSize, CommunicationGroup group = Communicator::AllGroup ); + + void setDistribution( LocalRangeType localRange, Index globalSize, CommunicationGroup group = Communicator::AllGroup ); + + const LocalRangeType& getLocalRange() const; + + CommunicationGroup getCommunicationGroup() const; + + // we return only the view so that the user cannot resize it + LocalArrayViewType getLocalArrayView(); + + ConstLocalArrayViewType getLocalArrayView() const; + + void copyFromGlobal( ConstLocalArrayViewType globalArray ); + + + static String getType(); + + virtual String getTypeVirtual() const; + + // TODO: no getSerializationType method until there is support for serialization + + + /* + * Usual Array methods follow below. + */ + template< typename Array > + void setLike( const Array& array ); + + void reset(); + + // TODO: swap + + // Returns the *global* size + IndexType getSize() const; + + // Sets all elements of the array to the given value + void setValue( ValueType value ); + + // Safe device-independent element setter + void setElement( IndexType i, ValueType value ); + + // Safe device-independent element getter + ValueType getElement( IndexType i ) const; + + // Unsafe element accessor usable only from the Device + __cuda_callable__ + ValueType& operator[]( IndexType i ); + + // Unsafe element accessor usable only from the Device + __cuda_callable__ + const ValueType& operator[]( IndexType i ) const; + + // Copy-assignment operator + DistributedArray& operator=( const DistributedArray& array ); + + template< typename Array > + DistributedArray& operator=( const Array& array ); + + // Comparison operators + template< typename Array > + bool operator==( const Array& array ) const; + + template< typename Array > + bool operator!=( const Array& array ) const; + + // Checks if there is an element with given value in this array + bool containsValue( ValueType value ) const; + + // Checks if all elements in this array have the same given value + bool containsOnlyValue( ValueType value ) const; + + // Returns true iff non-zero size is set + operator bool() const; + + // TODO: serialization (save, load, boundLoad) + +protected: + LocalRangeType localRange; + IndexType globalSize = 0; + CommunicationGroup group = Communicator::NullGroup; + LocalArrayType localData; + +private: + // TODO: disabled until they are implemented + using Object::save; + using Object::load; + using Object::boundLoad; +}; + +} // namespace DistributedContainers +} // namespace TNL + +#include "DistributedArray_impl.h" diff --git a/src/TNL/DistributedContainers/DistributedArrayView.h b/src/TNL/DistributedContainers/DistributedArrayView.h new file mode 100644 index 000000000..2575f1b79 --- /dev/null +++ b/src/TNL/DistributedContainers/DistributedArrayView.h @@ -0,0 +1,152 @@ +/*************************************************************************** + DistributedArrayView.h - description + ------------------- + begin : Sep 20, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by: Jakub Klinkovský + +#pragma once + +#include + +namespace TNL { +namespace DistributedContainers { + +template< typename Value, + typename Device = Devices::Host, + typename Index = int, + typename Communicator = Communicators::MpiCommunicator > +class DistributedArrayView +{ + using CommunicationGroup = typename Communicator::CommunicationGroup; +public: + using ValueType = Value; + using DeviceType = Device; + using CommunicatorType = Communicator; + using IndexType = Index; + using LocalRangeType = Subrange< Index >; + using LocalArrayViewType = Containers::ArrayView< Value, Device, Index >; + using ConstLocalArrayViewType = Containers::ArrayView< typename std::add_const< Value >::type, Device, Index >; + using HostType = DistributedArrayView< Value, Devices::Host, Index, Communicator >; + using CudaType = DistributedArrayView< Value, Devices::Cuda, Index, Communicator >; + + __cuda_callable__ + DistributedArrayView() = default; + + // Copy-constructor does shallow copy, so views can be passed-by-value into + // CUDA kernels and they can be captured-by-value in __cuda_callable__ + // lambda functions. + __cuda_callable__ + DistributedArrayView( const DistributedArrayView& ) = default; + + // "Templated copy-constructor" accepting any cv-qualification of Value + template< typename Value_ > + __cuda_callable__ + DistributedArrayView( const DistributedArrayView< Value_, Device, Index, Communicator >& ); + + // default move-constructor + __cuda_callable__ + DistributedArrayView( DistributedArrayView&& ) = default; + + // initialization from distributed array + template< typename Value_ > + DistributedArrayView( DistributedArray< Value_, Device, Index, Communicator >& array ); + + // this constructor will be used only when Value is const-qualified + // (const views are initializable by const references) + template< typename Value_ > + DistributedArrayView( const DistributedArray< Value_, Device, Index, Communicator >& array ); + + // method for rebinding (reinitialization) + // Note that you can also bind directly to Array and other types implicitly + // convertible to ArrayView. + __cuda_callable__ + void bind( DistributedArrayView view ); + + // binding to local array via raw pointer + // (local range, global size and communication group are preserved) + template< typename Value_ > + void bind( Value_* data, IndexType localSize ); + + + // Copy-assignment does deep copy, just like regular array, but the sizes + // must match (i.e. copy-assignment cannot resize). + DistributedArrayView& operator=( const DistributedArrayView& view ); + + template< typename Array > + DistributedArrayView& operator=( const Array& array ); + + + const LocalRangeType& getLocalRange() const; + + CommunicationGroup getCommunicationGroup() const; + + LocalArrayViewType getLocalArrayView(); + + ConstLocalArrayViewType getLocalArrayView() const; + + void copyFromGlobal( ConstLocalArrayViewType globalArray ); + + + static String getType(); + + + /* + * Usual ArrayView methods follow below. + */ + void reset(); + + // TODO: swap + + // Returns the *global* size + IndexType getSize() const; + + // Sets all elements of the array to the given value + void setValue( ValueType value ); + + // Safe device-independent element setter + void setElement( IndexType i, ValueType value ); + + // Safe device-independent element getter + ValueType getElement( IndexType i ) const; + + // Unsafe element accessor usable only from the Device + __cuda_callable__ + ValueType& operator[]( IndexType i ); + + // Unsafe element accessor usable only from the Device + __cuda_callable__ + const ValueType& operator[]( IndexType i ) const; + + // Comparison operators + template< typename Array > + bool operator==( const Array& array ) const; + + template< typename Array > + bool operator!=( const Array& array ) const; + + // Checks if there is an element with given value in this array + bool containsValue( ValueType value ) const; + + // Checks if all elements in this array have the same given value + bool containsOnlyValue( ValueType value ) const; + + // Returns true iff non-zero size is set + operator bool() const; + +protected: + LocalRangeType localRange; + IndexType globalSize = 0; + CommunicationGroup group = Communicator::NullGroup; + LocalArrayViewType localData; +}; + +} // namespace DistributedContainers +} // namespace TNL + +#include "DistributedArrayView_impl.h" diff --git a/src/TNL/DistributedContainers/DistributedArrayView_impl.h b/src/TNL/DistributedContainers/DistributedArrayView_impl.h new file mode 100644 index 000000000..fd974bba7 --- /dev/null +++ b/src/TNL/DistributedContainers/DistributedArrayView_impl.h @@ -0,0 +1,371 @@ +/*************************************************************************** + DistributedArrayView_impl.h - description + ------------------- + begin : Sep 20, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by: Jakub Klinkovský + +#pragma once + +#include "DistributedArrayView.h" + +namespace TNL { +namespace DistributedContainers { + +template< typename Value, + typename Device, + typename Index, + typename Communicator > + template< typename Value_ > +__cuda_callable__ +DistributedArrayView< Value, Device, Index, Communicator >:: +DistributedArrayView( const DistributedArrayView< Value_, Device, Index, Communicator >& view ) +: localRange( view.getLocalRange() ), + globalSize( view.getSize() ), + group( view.getCommunicationGroup() ), + localData( view.getLocalArrayView() ) +{} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > + template< typename Value_ > +DistributedArrayView< Value, Device, Index, Communicator >:: +DistributedArrayView( DistributedArray< Value_, Device, Index, Communicator >& array ) +: localRange( array.getLocalRange() ), + globalSize( array.getSize() ), + group( array.getCommunicationGroup() ), + localData( array.getLocalArrayView() ) +{} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > + template< typename Value_ > +DistributedArrayView< Value, Device, Index, Communicator >:: +DistributedArrayView( const DistributedArray< Value_, Device, Index, Communicator >& array ) +: localRange( array.getLocalRange() ), + globalSize( array.getSize() ), + group( array.getCommunicationGroup() ), + localData( array.getLocalArrayView() ) +{} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +__cuda_callable__ +void +DistributedArrayView< Value, Device, Index, Communicator >:: +bind( DistributedArrayView view ) +{ + localRange = view.getLocalRange(); + globalSize = view.getSize(); + group = view.getCommunicationGroup(); + localData.bind( view.getLocalArrayView() ); +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > + template< typename Value_ > +void +DistributedArrayView< Value, Device, Index, Communicator >:: +bind( Value_* data, IndexType localSize ) +{ + TNL_ASSERT_EQ( localSize, localRange.getSize(), + "The local array size does not match the local range of the distributed array." ); + localData.bind( data, localSize ); +} + + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +DistributedArrayView< Value, Device, Index, Communicator >& +DistributedArrayView< Value, Device, Index, Communicator >:: +operator=( const DistributedArrayView& view ) +{ + TNL_ASSERT_EQ( getSize(), view.getSize(), "The sizes of the array views must be equal, views are not resizable." ); + TNL_ASSERT_EQ( getLocalRange(), view.getLocalRange(), "The local ranges must be equal, views are not resizable." ); + TNL_ASSERT_EQ( getCommunicationGroup(), view.getCommunicationGroup(), "The communication groups of the array views must be equal." ); + localData = view.getLocalArrayView(); + return *this; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > + template< typename Array > +DistributedArrayView< Value, Device, Index, Communicator >& +DistributedArrayView< Value, Device, Index, Communicator >:: +operator=( const Array& array ) +{ + TNL_ASSERT_EQ( getSize(), array.getSize(), "The global sizes must be equal, views are not resizable." ); + TNL_ASSERT_EQ( getLocalRange(), array.getLocalRange(), "The local ranges must be equal, views are not resizable." ); + TNL_ASSERT_EQ( getCommunicationGroup(), array.getCommunicationGroup(), "The communication groups must be equal." ); + localData = array.getLocalArrayView(); + return *this; +} + + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +const Subrange< Index >& +DistributedArrayView< Value, Device, Index, Communicator >:: +getLocalRange() const +{ + return localRange; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +typename Communicator::CommunicationGroup +DistributedArrayView< Value, Device, Index, Communicator >:: +getCommunicationGroup() const +{ + return group; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +typename DistributedArrayView< Value, Device, Index, Communicator >::LocalArrayViewType +DistributedArrayView< Value, Device, Index, Communicator >:: +getLocalArrayView() +{ + return localData; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +typename DistributedArrayView< Value, Device, Index, Communicator >::ConstLocalArrayViewType +DistributedArrayView< Value, Device, Index, Communicator >:: +getLocalArrayView() const +{ + return localData; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +void +DistributedArrayView< Value, Device, Index, Communicator >:: +copyFromGlobal( ConstLocalArrayViewType globalArray ) +{ + TNL_ASSERT_EQ( getSize(), globalArray.getSize(), + "given global array has different size than the distributed array view" ); + + LocalArrayViewType localView( localData ); + const LocalRangeType localRange = getLocalRange(); + + auto kernel = [=] __cuda_callable__ ( IndexType i ) mutable + { + localView[ i ] = globalArray[ localRange.getGlobalIndex( i ) ]; + }; + + ParallelFor< DeviceType >::exec( (IndexType) 0, localRange.getSize(), kernel ); +} + + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +String +DistributedArrayView< Value, Device, Index, Communicator >:: +getType() +{ + return String( "DistributedContainers::DistributedArrayView< " ) + + TNL::getType< Value >() + ", " + + Device::getDeviceType() + ", " + + TNL::getType< Index >() + ", " + + // TODO: communicators don't have a getType method + " >"; +} + + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +void +DistributedArrayView< Value, Device, Index, Communicator >:: +reset() +{ + localRange.reset(); + globalSize = 0; + group = Communicator::NullGroup; + localData.reset(); +} + +// TODO: swap + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +Index +DistributedArrayView< Value, Device, Index, Communicator >:: +getSize() const +{ + return globalSize; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +void +DistributedArrayView< Value, Device, Index, Communicator >:: +setValue( ValueType value ) +{ + localData.setValue( value ); +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +void +DistributedArrayView< Value, Device, Index, Communicator >:: +setElement( IndexType i, ValueType value ) +{ + const IndexType li = localRange.getLocalIndex( i ); + localData.setElement( li, value ); +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +Value +DistributedArrayView< Value, Device, Index, Communicator >:: +getElement( IndexType i ) const +{ + const IndexType li = localRange.getLocalIndex( i ); + return localData.getElement( li ); +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +__cuda_callable__ +Value& +DistributedArrayView< Value, Device, Index, Communicator >:: +operator[]( IndexType i ) +{ + const IndexType li = localRange.getLocalIndex( i ); + return localData[ li ]; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +__cuda_callable__ +const Value& +DistributedArrayView< Value, Device, Index, Communicator >:: +operator[]( IndexType i ) const +{ + const IndexType li = localRange.getLocalIndex( i ); + return localData[ li ]; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > + template< typename Array > +bool +DistributedArrayView< Value, Device, Index, Communicator >:: +operator==( const Array& array ) const +{ + // we can't run allreduce if the communication groups are different + if( group != array.getCommunicationGroup() ) + return false; + const bool localResult = + localRange == array.getLocalRange() && + globalSize == array.getSize() && + localData == array.getLocalArrayView(); + bool result = true; + if( group != CommunicatorType::NullGroup ) + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, group ); + return result; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > + template< typename Array > +bool +DistributedArrayView< Value, Device, Index, Communicator >:: +operator!=( const Array& array ) const +{ + return ! (*this == array); +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +bool +DistributedArrayView< Value, Device, Index, Communicator >:: +containsValue( ValueType value ) const +{ + bool result = false; + if( group != CommunicatorType::NullGroup ) { + const bool localResult = localData.containsValue( value ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LOR, group ); + } + return result; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +bool +DistributedArrayView< Value, Device, Index, Communicator >:: +containsOnlyValue( ValueType value ) const +{ + bool result = true; + if( group != CommunicatorType::NullGroup ) { + const bool localResult = localData.containsOnlyValue( value ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, group ); + } + return result; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +DistributedArrayView< Value, Device, Index, Communicator >:: +operator bool() const +{ + return getSize() != 0; +} + +} // namespace DistributedContainers +} // namespace TNL diff --git a/src/TNL/DistributedContainers/DistributedArray_impl.h b/src/TNL/DistributedContainers/DistributedArray_impl.h new file mode 100644 index 000000000..7731bd6be --- /dev/null +++ b/src/TNL/DistributedContainers/DistributedArray_impl.h @@ -0,0 +1,352 @@ +/*************************************************************************** + DistributedArray_impl.h - description + ------------------- + begin : Sep 6, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by: Jakub Klinkovský + +#pragma once + +#include "DistributedArray.h" + +#include +#include // important only when MPI is disabled + +namespace TNL { +namespace DistributedContainers { + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +DistributedArray< Value, Device, Index, Communicator >:: +DistributedArray( LocalRangeType localRange, IndexType globalSize, CommunicationGroup group ) +{ + setDistribution( localRange, globalSize, group ); +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +void +DistributedArray< Value, Device, Index, Communicator >:: +setDistribution( LocalRangeType localRange, IndexType globalSize, CommunicationGroup group ) +{ + TNL_ASSERT_LE( localRange.getEnd(), globalSize, "end of the local range is outside of the global range" ); + this->localRange = localRange; + this->globalSize = globalSize; + this->group = group; + if( group != Communicator::NullGroup ) + localData.setSize( localRange.getSize() ); +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +const Subrange< Index >& +DistributedArray< Value, Device, Index, Communicator >:: +getLocalRange() const +{ + return localRange; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +typename Communicator::CommunicationGroup +DistributedArray< Value, Device, Index, Communicator >:: +getCommunicationGroup() const +{ + return group; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +typename DistributedArray< Value, Device, Index, Communicator >::LocalArrayViewType +DistributedArray< Value, Device, Index, Communicator >:: +getLocalArrayView() +{ + return localData; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +typename DistributedArray< Value, Device, Index, Communicator >::ConstLocalArrayViewType +DistributedArray< Value, Device, Index, Communicator >:: +getLocalArrayView() const +{ + return localData; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +void +DistributedArray< Value, Device, Index, Communicator >:: +copyFromGlobal( ConstLocalArrayViewType globalArray ) +{ + TNL_ASSERT_EQ( getSize(), globalArray.getSize(), + "given global array has different size than the distributed array" ); + + LocalArrayViewType localView( localData ); + const LocalRangeType localRange = getLocalRange(); + + auto kernel = [=] __cuda_callable__ ( IndexType i ) mutable + { + localView[ i ] = globalArray[ localRange.getGlobalIndex( i ) ]; + }; + + ParallelFor< DeviceType >::exec( (IndexType) 0, localRange.getSize(), kernel ); +} + + +/* + * Usual Array methods follow below. + */ + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +String +DistributedArray< Value, Device, Index, Communicator >:: +getType() +{ + return String( "DistributedContainers::DistributedArray< " ) + + TNL::getType< Value >() + ", " + + Device::getDeviceType() + ", " + + TNL::getType< Index >() + ", " + + // TODO: communicators don't have a getType method + " >"; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +String +DistributedArray< Value, Device, Index, Communicator >:: +getTypeVirtual() const +{ + return getType(); +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > + template< typename Array > +void +DistributedArray< Value, Device, Index, Communicator >:: +setLike( const Array& array ) +{ + localRange = array.getLocalRange(); + globalSize = array.getSize(); + group = array.getCommunicationGroup(); + localData.setLike( array.getLocalArrayView() ); +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +void +DistributedArray< Value, Device, Index, Communicator >:: +reset() +{ + localRange.reset(); + globalSize = 0; + group = Communicator::NullGroup; + localData.reset(); +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +Index +DistributedArray< Value, Device, Index, Communicator >:: +getSize() const +{ + return globalSize; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +void +DistributedArray< Value, Device, Index, Communicator >:: +setValue( ValueType value ) +{ + localData.setValue( value ); +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +void +DistributedArray< Value, Device, Index, Communicator >:: +setElement( IndexType i, ValueType value ) +{ + const IndexType li = localRange.getLocalIndex( i ); + localData.setElement( li, value ); +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +Value +DistributedArray< Value, Device, Index, Communicator >:: +getElement( IndexType i ) const +{ + const IndexType li = localRange.getLocalIndex( i ); + return localData.getElement( li ); +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +__cuda_callable__ +Value& +DistributedArray< Value, Device, Index, Communicator >:: +operator[]( IndexType i ) +{ + const IndexType li = localRange.getLocalIndex( i ); + return localData[ li ]; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +__cuda_callable__ +const Value& +DistributedArray< Value, Device, Index, Communicator >:: +operator[]( IndexType i ) const +{ + const IndexType li = localRange.getLocalIndex( i ); + return localData[ li ]; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +DistributedArray< Value, Device, Index, Communicator >& +DistributedArray< Value, Device, Index, Communicator >:: +operator=( const DistributedArray& array ) +{ + setLike( array ); + localData = array.getLocalArrayView(); + return *this; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > + template< typename Array > +DistributedArray< Value, Device, Index, Communicator >& +DistributedArray< Value, Device, Index, Communicator >:: +operator=( const Array& array ) +{ + setLike( array ); + localData = array.getLocalArrayView(); + return *this; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > + template< typename Array > +bool +DistributedArray< Value, Device, Index, Communicator >:: +operator==( const Array& array ) const +{ + // we can't run allreduce if the communication groups are different + if( group != array.getCommunicationGroup() ) + return false; + const bool localResult = + localRange == array.getLocalRange() && + globalSize == array.getSize() && + localData == array.getLocalArrayView(); + bool result = true; + if( group != CommunicatorType::NullGroup ) + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, group ); + return result; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > + template< typename Array > +bool +DistributedArray< Value, Device, Index, Communicator >:: +operator!=( const Array& array ) const +{ + return ! (*this == array); +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +bool +DistributedArray< Value, Device, Index, Communicator >:: +containsValue( ValueType value ) const +{ + bool result = false; + if( group != CommunicatorType::NullGroup ) { + const bool localResult = localData.containsValue( value ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LOR, group ); + } + return result; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +bool +DistributedArray< Value, Device, Index, Communicator >:: +containsOnlyValue( ValueType value ) const +{ + bool result = true; + if( group != CommunicatorType::NullGroup ) { + const bool localResult = localData.containsOnlyValue( value ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, group ); + } + return result; +} + +template< typename Value, + typename Device, + typename Index, + typename Communicator > +DistributedArray< Value, Device, Index, Communicator >:: +operator bool() const +{ + return getSize() != 0; +} + +} // namespace DistributedContainers +} // namespace TNL diff --git a/src/TNL/DistributedContainers/DistributedMatrix.h b/src/TNL/DistributedContainers/DistributedMatrix.h new file mode 100644 index 000000000..52d98b264 --- /dev/null +++ b/src/TNL/DistributedContainers/DistributedMatrix.h @@ -0,0 +1,186 @@ +/*************************************************************************** + DistributedMatrix.h - description + ------------------- + begin : Sep 10, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by: Jakub Klinkovský + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include + +namespace TNL { +namespace DistributedContainers { + +template< typename T, typename R = void > +struct enable_if_type +{ + using type = R; +}; + +template< typename T, typename Enable = void > +struct has_communicator : std::false_type {}; + +template< typename T > +struct has_communicator< T, typename enable_if_type< typename T::CommunicatorType >::type > +: std::true_type +{}; + + +// TODO: 2D distribution for dense matrices (maybe it should be in different template, +// because e.g. setRowFast doesn't make sense for dense matrices) +template< typename Matrix, + typename Communicator = Communicators::MpiCommunicator > +class DistributedMatrix +: public Object +{ + using CommunicationGroup = typename Communicator::CommunicationGroup; +public: + using MatrixType = Matrix; + using RealType = typename Matrix::RealType; + using DeviceType = typename Matrix::DeviceType; + using IndexType = typename Matrix::IndexType; + using CommunicatorType = Communicator; + using LocalRangeType = Subrange< typename Matrix::IndexType >; + + using HostType = DistributedMatrix< typename Matrix::HostType, Communicator >; + using CudaType = DistributedMatrix< typename Matrix::CudaType, Communicator >; + + using CompressedRowLengthsVector = DistributedVector< IndexType, DeviceType, IndexType, CommunicatorType >; + + using MatrixRow = Matrices::SparseRow< RealType, IndexType >; + using ConstMatrixRow = Matrices::SparseRow< typename std::add_const< RealType >::type, typename std::add_const< IndexType >::type >; + + DistributedMatrix() = default; + + DistributedMatrix( DistributedMatrix& ) = default; + + DistributedMatrix( LocalRangeType localRowRange, IndexType rows, IndexType columns, CommunicationGroup group = Communicator::AllGroup ); + + void setDistribution( LocalRangeType localRowRange, IndexType rows, IndexType columns, CommunicationGroup group = Communicator::AllGroup ); + + __cuda_callable__ + const LocalRangeType& getLocalRowRange() const; + + __cuda_callable__ + CommunicationGroup getCommunicationGroup() const; + + __cuda_callable__ + const Matrix& getLocalMatrix() const; + + + static String getType(); + + virtual String getTypeVirtual() const; + + // TODO: no getSerializationType method until there is support for serialization + + + /* + * Some common Matrix methods follow below. + */ + + DistributedMatrix& operator=( const DistributedMatrix& matrix ); + + template< typename MatrixT > + DistributedMatrix& operator=( const MatrixT& matrix ); + + template< typename MatrixT > + void setLike( const MatrixT& matrix ); + + void reset(); + + __cuda_callable__ + IndexType getRows() const; + + __cuda_callable__ + IndexType getColumns() const; + + void setCompressedRowLengths( const CompressedRowLengthsVector& rowLengths ); + + void getCompressedRowLengths( CompressedRowLengthsVector& rowLengths ) const; + + IndexType getRowLength( IndexType row ) const; + + bool setElement( IndexType row, + IndexType column, + RealType value ); + + __cuda_callable__ + bool setElementFast( IndexType row, + IndexType column, + RealType value ); + + RealType getElement( IndexType row, + IndexType column ) const; + + __cuda_callable__ + RealType getElementFast( IndexType row, + IndexType column ) const; + + __cuda_callable__ + bool setRowFast( IndexType row, + const IndexType* columnIndexes, + const RealType* values, + IndexType elements ); + + __cuda_callable__ + void getRowFast( IndexType row, + IndexType* columns, + RealType* values ) const; + + __cuda_callable__ + MatrixRow getRow( IndexType row ); + + __cuda_callable__ + ConstMatrixRow getRow( IndexType row ) const; + + // multiplication with a global vector + template< typename InVector, + typename OutVector > + typename std::enable_if< ! has_communicator< InVector >::value >::type + vectorProduct( const InVector& inVector, + OutVector& outVector ) const; + + // Optimization for distributed matrix-vector multiplication + void updateVectorProductCommunicationPattern(); + + // multiplication with a distributed vector + // (not const because it modifies internal bufers) + template< typename InVector, + typename OutVector > + typename std::enable_if< has_communicator< InVector >::value >::type + vectorProduct( const InVector& inVector, + OutVector& outVector ) const; + +protected: + LocalRangeType localRowRange; + IndexType rows = 0; // global rows count + CommunicationGroup group = Communicator::NullGroup; + Matrix localMatrix; + + DistributedSpMV< Matrix, Communicator > spmv; + +private: + // TODO: disabled until they are implemented + using Object::save; + using Object::load; + using Object::boundLoad; +}; + +} // namespace DistributedContainers +} // namespace TNL + +#include "DistributedMatrix_impl.h" diff --git a/src/TNL/DistributedContainers/DistributedMatrix_impl.h b/src/TNL/DistributedContainers/DistributedMatrix_impl.h new file mode 100644 index 000000000..1fad8486c --- /dev/null +++ b/src/TNL/DistributedContainers/DistributedMatrix_impl.h @@ -0,0 +1,360 @@ +/*************************************************************************** + DistributedMatrix.h - description + ------------------- + begin : Sep 10, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by: Jakub Klinkovský + +#pragma once + +#include "DistributedMatrix.h" + +namespace TNL { +namespace DistributedContainers { + +template< typename Matrix, + typename Communicator > +DistributedMatrix< Matrix, Communicator >:: +DistributedMatrix( LocalRangeType localRowRange, IndexType rows, IndexType columns, CommunicationGroup group ) +{ + setDistribution( localRowRange, rows, columns, group ); +} + +template< typename Matrix, + typename Communicator > +void +DistributedMatrix< Matrix, Communicator >:: +setDistribution( LocalRangeType localRowRange, IndexType rows, IndexType columns, CommunicationGroup group ) +{ + this->localRowRange = localRowRange; + this->rows = rows; + this->group = group; + if( group != Communicator::NullGroup ) + localMatrix.setDimensions( localRowRange.getSize(), columns ); + + spmv.reset(); +} + +template< typename Matrix, + typename Communicator > +__cuda_callable__ +const Subrange< typename Matrix::IndexType >& +DistributedMatrix< Matrix, Communicator >:: +getLocalRowRange() const +{ + return localRowRange; +} + +template< typename Matrix, + typename Communicator > +__cuda_callable__ +typename Communicator::CommunicationGroup +DistributedMatrix< Matrix, Communicator >:: +getCommunicationGroup() const +{ + return group; +} + +template< typename Matrix, + typename Communicator > +__cuda_callable__ +const Matrix& +DistributedMatrix< Matrix, Communicator >:: +getLocalMatrix() const +{ + return localMatrix; +} + + +template< typename Matrix, + typename Communicator > +String +DistributedMatrix< Matrix, Communicator >:: +getType() +{ + return String( "DistributedContainers::DistributedMatrix< " ) + + Matrix::getType() + ", " + + // TODO: communicators don't have a getType method + "" + " >"; +} + +template< typename Matrix, + typename Communicator > +String +DistributedMatrix< Matrix, Communicator >:: +getTypeVirtual() const +{ + return getType(); +} + + +/* + * Some common Matrix methods follow below. + */ + +template< typename Matrix, + typename Communicator > +DistributedMatrix< Matrix, Communicator >& +DistributedMatrix< Matrix, Communicator >:: +operator=( const DistributedMatrix& matrix ) +{ + setLike( matrix ); + localMatrix = matrix.getLocalMatrix(); + return *this; +} + +template< typename Matrix, + typename Communicator > + template< typename MatrixT > +DistributedMatrix< Matrix, Communicator >& +DistributedMatrix< Matrix, Communicator >:: +operator=( const MatrixT& matrix ) +{ + setLike( matrix ); + localMatrix = matrix.getLocalMatrix(); + return *this; +} + +template< typename Matrix, + typename Communicator > + template< typename MatrixT > +void +DistributedMatrix< Matrix, Communicator >:: +setLike( const MatrixT& matrix ) +{ + localRowRange = matrix.getLocalRowRange(); + rows = matrix.getRows(); + group = matrix.getCommunicationGroup(); + localMatrix.setLike( matrix.getLocalMatrix() ); + + spmv.reset(); +} + +template< typename Matrix, + typename Communicator > +void +DistributedMatrix< Matrix, Communicator >:: +reset() +{ + localRowRange.reset(); + rows = 0; + group = Communicator::NullGroup; + localMatrix.reset(); + + spmv.reset(); +} + +template< typename Matrix, + typename Communicator > +__cuda_callable__ +typename Matrix::IndexType +DistributedMatrix< Matrix, Communicator >:: +getRows() const +{ + return rows; +} + +template< typename Matrix, + typename Communicator > +__cuda_callable__ +typename Matrix::IndexType +DistributedMatrix< Matrix, Communicator >:: +getColumns() const +{ + return localMatrix.getColumns(); +} + +template< typename Matrix, + typename Communicator > +void +DistributedMatrix< Matrix, Communicator >:: +setCompressedRowLengths( const CompressedRowLengthsVector& rowLengths ) +{ + TNL_ASSERT_EQ( rowLengths.getSize(), getRows(), "row lengths vector has wrong size" ); + TNL_ASSERT_EQ( rowLengths.getLocalRange(), getLocalRowRange(), "row lengths vector has wrong distribution" ); + TNL_ASSERT_EQ( rowLengths.getCommunicationGroup(), getCommunicationGroup(), "row lengths vector has wrong communication group" ); + + if( getCommunicationGroup() != CommunicatorType::NullGroup ) { + localMatrix.setCompressedRowLengths( rowLengths.getLocalVectorView() ); + + spmv.reset(); + } +} + +template< typename Matrix, + typename Communicator > +void +DistributedMatrix< Matrix, Communicator >:: +getCompressedRowLengths( CompressedRowLengthsVector& rowLengths ) const +{ + if( getCommunicationGroup() != CommunicatorType::NullGroup ) { + rowLengths.setDistribution( getLocalRowRange(), getRows(), getCommunicationGroup() ); + localMatrix.getCompressedRowLengths( rowLengths.getLocalVectorView() ); + } +} + +template< typename Matrix, + typename Communicator > +typename Matrix::IndexType +DistributedMatrix< Matrix, Communicator >:: +getRowLength( IndexType row ) const +{ + const IndexType localRow = localRowRange.getLocalIndex( row ); + return localMatrix.getRowLength( localRow ); +} + +template< typename Matrix, + typename Communicator > +bool +DistributedMatrix< Matrix, Communicator >:: +setElement( IndexType row, + IndexType column, + RealType value ) +{ + const IndexType localRow = localRowRange.getLocalIndex( row ); + return localMatrix.setElement( localRow, column, value ); +} + +template< typename Matrix, + typename Communicator > +__cuda_callable__ +bool +DistributedMatrix< Matrix, Communicator >:: +setElementFast( IndexType row, + IndexType column, + RealType value ) +{ + const IndexType localRow = localRowRange.getLocalIndex( row ); + return localMatrix.setElementFast( localRow, column, value ); +} + +template< typename Matrix, + typename Communicator > +typename Matrix::RealType +DistributedMatrix< Matrix, Communicator >:: +getElement( IndexType row, + IndexType column ) const +{ + const IndexType localRow = localRowRange.getLocalIndex( row ); + return localMatrix.getElement( localRow, column ); +} + +template< typename Matrix, + typename Communicator > +__cuda_callable__ +typename Matrix::RealType +DistributedMatrix< Matrix, Communicator >:: +getElementFast( IndexType row, + IndexType column ) const +{ + const IndexType localRow = localRowRange.getLocalIndex( row ); + return localMatrix.getElementFast( localRow, column ); +} + +template< typename Matrix, + typename Communicator > +__cuda_callable__ +bool +DistributedMatrix< Matrix, Communicator >:: +setRowFast( IndexType row, + const IndexType* columnIndexes, + const RealType* values, + IndexType elements ) +{ + const IndexType localRow = localRowRange.getLocalIndex( row ); + return localMatrix.setRowFast( localRow, columnIndexes, values, elements ); +} + +template< typename Matrix, + typename Communicator > +__cuda_callable__ +void +DistributedMatrix< Matrix, Communicator >:: +getRowFast( IndexType row, + IndexType* columns, + RealType* values ) const +{ + const IndexType localRow = localRowRange.getLocalIndex( row ); + return localMatrix.getRowFast( localRow, columns, values ); +} + +template< typename Matrix, + typename Communicator > +__cuda_callable__ +typename DistributedMatrix< Matrix, Communicator >::MatrixRow +DistributedMatrix< Matrix, Communicator >:: +getRow( IndexType row ) +{ + const IndexType localRow = localRowRange.getLocalIndex( row ); + return localMatrix.getRow( localRow ); +} + +template< typename Matrix, + typename Communicator > +__cuda_callable__ +typename DistributedMatrix< Matrix, Communicator >::ConstMatrixRow +DistributedMatrix< Matrix, Communicator >:: +getRow( IndexType row ) const +{ + const IndexType localRow = localRowRange.getLocalIndex( row ); + return localMatrix.getRow( localRow ); +} + +template< typename Matrix, + typename Communicator > + template< typename InVector, + typename OutVector > +typename std::enable_if< ! has_communicator< InVector >::value >::type +DistributedMatrix< Matrix, Communicator >:: +vectorProduct( const InVector& inVector, + OutVector& outVector ) const +{ + TNL_ASSERT_EQ( inVector.getSize(), getColumns(), "input vector has wrong size" ); + TNL_ASSERT_EQ( outVector.getSize(), getRows(), "output vector has wrong size" ); + TNL_ASSERT_EQ( outVector.getLocalRange(), getLocalRowRange(), "output vector has wrong distribution" ); + TNL_ASSERT_EQ( outVector.getCommunicationGroup(), getCommunicationGroup(), "output vector has wrong communication group" ); + + auto outView = outVector.getLocalVectorView(); + localMatrix.vectorProduct( inVector, outView ); +} + +template< typename Matrix, + typename Communicator > +void +DistributedMatrix< Matrix, Communicator >:: +updateVectorProductCommunicationPattern() +{ + if( getCommunicationGroup() == CommunicatorType::NullGroup ) + return; + spmv.updateCommunicationPattern( getLocalMatrix(), getCommunicationGroup() ); +} + +template< typename Matrix, + typename Communicator > + template< typename InVector, + typename OutVector > +typename std::enable_if< has_communicator< InVector >::value >::type +DistributedMatrix< Matrix, Communicator >:: +vectorProduct( const InVector& inVector, + OutVector& outVector ) const +{ + TNL_ASSERT_EQ( inVector.getSize(), getColumns(), "input vector has wrong size" ); + TNL_ASSERT_EQ( inVector.getLocalRange(), getLocalRowRange(), "input vector has wrong distribution" ); + TNL_ASSERT_EQ( inVector.getCommunicationGroup(), getCommunicationGroup(), "input vector has wrong communication group" ); + TNL_ASSERT_EQ( outVector.getSize(), getRows(), "output vector has wrong size" ); + TNL_ASSERT_EQ( outVector.getLocalRange(), getLocalRowRange(), "output vector has wrong distribution" ); + TNL_ASSERT_EQ( outVector.getCommunicationGroup(), getCommunicationGroup(), "output vector has wrong communication group" ); + + if( getCommunicationGroup() == CommunicatorType::NullGroup ) + return; + + const_cast< DistributedMatrix* >( this )->spmv.vectorProduct( outVector, localMatrix, inVector, getCommunicationGroup() ); +} + +} // namespace DistributedContainers +} // namespace TNL diff --git a/src/TNL/DistributedContainers/DistributedSpMV.h b/src/TNL/DistributedContainers/DistributedSpMV.h new file mode 100644 index 000000000..9bc47d739 --- /dev/null +++ b/src/TNL/DistributedContainers/DistributedSpMV.h @@ -0,0 +1,221 @@ +/*************************************************************************** + DistributedSpMV.h - description + ------------------- + begin : Sep 20, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by: Jakub Klinkovský + +#pragma once + +#include +#include + +// buffers +#include +#include // std::pair +#include +#include +#include + +// operations +#include // std::add_const +#include +#include +#include + +namespace TNL { +namespace DistributedContainers { + +template< typename Matrix, typename Communicator > +class DistributedSpMV +{ +public: + using MatrixType = Matrix; + using RealType = typename Matrix::RealType; + using DeviceType = typename Matrix::DeviceType; + using IndexType = typename Matrix::IndexType; + using CommunicatorType = Communicator; + using CommunicationGroup = typename CommunicatorType::CommunicationGroup; + using Partitioner = DistributedContainers::Partitioner< typename Matrix::IndexType, Communicator >; + + // - communication pattern matrix is an nproc x nproc binary matrix C, where + // C_ij = 1 iff the i-th process needs data from the j-th process + // - assembly of the i-th row involves traversal of the local matrix stored + // in the i-th process + // - assembly the full matrix needs all-to-all communication + void updateCommunicationPattern( const MatrixType& localMatrix, CommunicationGroup group ) + { + const int rank = CommunicatorType::GetRank( group ); + const int nproc = CommunicatorType::GetSize( group ); + commPattern.setDimensions( nproc, nproc ); + + // pass the localMatrix to the device + const Pointers::DevicePointer< const MatrixType > localMatrixPointer( localMatrix ); + + // buffer for the local row of the commPattern matrix +// using AtomicBool = Atomic< bool, DeviceType >; + // FIXME: CUDA does not support atomic operations for bool + using AtomicBool = Atomic< int, DeviceType >; + Containers::Array< AtomicBool, DeviceType > buffer( nproc ); + buffer.setValue( false ); + + // optimization for banded matrices + using AtomicIndex = Atomic< IndexType, DeviceType >; + Containers::Array< AtomicIndex, DeviceType > local_span( 2 ); + local_span.setElement( 0, 0 ); // span start + local_span.setElement( 1, localMatrix.getRows() ); // span end + + auto kernel = [=] __cuda_callable__ ( IndexType i, const MatrixType* localMatrix, + AtomicBool* buffer, AtomicIndex* local_span ) + { + const IndexType columns = localMatrix->getColumns(); + const auto row = localMatrix->getRow( i ); + bool comm_left = false; + bool comm_right = false; + for( IndexType c = 0; c < row.getLength(); c++ ) { + const IndexType j = row.getElementColumn( c ); + if( j < columns ) { + const int owner = Partitioner::getOwner( j, columns, nproc ); + // atomic assignment + buffer[ owner ].store( true ); + // update comm_left/Right + if( owner < rank ) + comm_left = true; + if( owner > rank ) + comm_right = true; + } + } + // update local span + if( comm_left ) + local_span[0].fetch_max( i + 1 ); + if( comm_right ) + local_span[1].fetch_min( i ); + }; + + ParallelFor< DeviceType >::exec( (IndexType) 0, localMatrix.getRows(), + kernel, + &localMatrixPointer.template getData< DeviceType >(), + buffer.getData(), + local_span.getData() + ); + + // set the local-only span (optimization for banded matrices) + localOnlySpan.first = local_span.getElement( 0 ); + localOnlySpan.second = local_span.getElement( 1 ); + + // copy the buffer into all rows of the preCommPattern matrix + Matrices::Dense< bool, Devices::Host, int > preCommPattern; + preCommPattern.setLike( commPattern ); + for( int j = 0; j < nproc; j++ ) + for( int i = 0; i < nproc; i++ ) + preCommPattern.setElementFast( j, i, buffer.getElement( i ) ); + + // assemble the commPattern matrix + CommunicatorType::Alltoall( &preCommPattern(0, 0), nproc, + &commPattern(0, 0), nproc, + group ); + } + + template< typename InVector, + typename OutVector > + void vectorProduct( OutVector& outVector, + const MatrixType& localMatrix, + const InVector& inVector, + CommunicationGroup group ) + { + const int rank = CommunicatorType::GetRank( group ); + const int nproc = CommunicatorType::GetSize( group ); + + // update communication pattern + if( commPattern.getRows() != nproc ) + updateCommunicationPattern( localMatrix, group ); + + // prepare buffers + globalBuffer.setSize( localMatrix.getColumns() ); + commRequests.clear(); + + // send our data to all processes that need it + for( int i = 0; i < commPattern.getRows(); i++ ) + if( commPattern( i, rank ) ) + commRequests.push_back( CommunicatorType::ISend( + inVector.getLocalVectorView().getData(), + inVector.getLocalVectorView().getSize(), + i, group ) ); + + // receive data that we need + for( int j = 0; j < commPattern.getRows(); j++ ) + if( commPattern( rank, j ) ) + commRequests.push_back( CommunicatorType::IRecv( + &globalBuffer[ Partitioner::getOffset( globalBuffer.getSize(), j, nproc ) ], + Partitioner::getSizeForRank( globalBuffer.getSize(), j, nproc ), + j, group ) ); + + // general variant + if( localOnlySpan.first >= localOnlySpan.second ) { + // wait for all communications to finish + CommunicatorType::WaitAll( &commRequests[0], commRequests.size() ); + + // perform matrix-vector multiplication + auto outView = outVector.getLocalVectorView(); + localMatrix.vectorProduct( globalBuffer, outView ); + } + // optimization for banded matrices + else { + auto outVectorView = outVector.getLocalVectorView(); + const Pointers::DevicePointer< const MatrixType > localMatrixPointer( localMatrix ); + using InView = DistributedVectorView< const typename InVector::RealType, typename InVector::DeviceType, typename InVector::IndexType, typename InVector::CommunicatorType >; + const InView inView( inVector ); + + // matrix-vector multiplication using local-only rows + auto kernel1 = [=] __cuda_callable__ ( IndexType i, const MatrixType* localMatrix ) mutable + { + outVectorView[ i ] = localMatrix->rowVectorProduct( i, inView ); + }; + ParallelFor< DeviceType >::exec( localOnlySpan.first, localOnlySpan.second, kernel1, + &localMatrixPointer.template getData< DeviceType >() ); + + // wait for all communications to finish + CommunicatorType::WaitAll( &commRequests[0], commRequests.size() ); + + // finish the multiplication by adding the non-local entries + Containers::VectorView< RealType, DeviceType, IndexType > globalBufferView( globalBuffer ); + auto kernel2 = [=] __cuda_callable__ ( IndexType i, const MatrixType* localMatrix ) mutable + { + outVectorView[ i ] = localMatrix->rowVectorProduct( i, globalBufferView ); + }; + ParallelFor< DeviceType >::exec( (IndexType) 0, localOnlySpan.first, kernel2, + &localMatrixPointer.template getData< DeviceType >() ); + ParallelFor< DeviceType >::exec( localOnlySpan.second, localMatrix.getRows(), kernel2, + &localMatrixPointer.template getData< DeviceType >() ); + } + } + + void reset() + { + commPattern.reset(); + localOnlySpan.first = localOnlySpan.second = 0; + globalBuffer.reset(); + commRequests.clear(); + } + +protected: + // communication pattern + Matrices::Dense< bool, Devices::Host, int > commPattern; + + // span of rows with only block-diagonal entries + std::pair< IndexType, IndexType > localOnlySpan; + + // global buffer for non-local elements of the vector + Containers::Vector< RealType, DeviceType, IndexType > globalBuffer; + + // buffer for asynchronous communication requests + std::vector< typename CommunicatorType::Request > commRequests; +}; + +} // namespace DistributedContainers +} // namespace TNL diff --git a/src/TNL/DistributedContainers/DistributedVector.h b/src/TNL/DistributedContainers/DistributedVector.h new file mode 100644 index 000000000..81853315b --- /dev/null +++ b/src/TNL/DistributedContainers/DistributedVector.h @@ -0,0 +1,139 @@ +/*************************************************************************** + DistributedVector.h - description + ------------------- + begin : Sep 7, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by: Jakub Klinkovský + +#pragma once + +#include "DistributedArray.h" +#include + +namespace TNL { +namespace DistributedContainers { + +template< typename Real, + typename Device = Devices::Host, + typename Index = int, + typename Communicator = Communicators::MpiCommunicator > +class DistributedVector +: public DistributedArray< Real, Device, Index, Communicator > +{ + using CommunicationGroup = typename Communicator::CommunicationGroup; + using BaseType = DistributedArray< Real, Device, Index, Communicator >; +public: + using RealType = Real; + using DeviceType = Device; + using CommunicatorType = Communicator; + using IndexType = Index; + using LocalVectorViewType = Containers::VectorView< Real, Device, Index >; + using ConstLocalVectorViewType = Containers::VectorView< typename std::add_const< Real >::type, Device, Index >; + using HostType = DistributedVector< Real, Devices::Host, Index, Communicator >; + using CudaType = DistributedVector< Real, Devices::Cuda, Index, Communicator >; + + // inherit all constructors and assignment operators from Array + using BaseType::DistributedArray; + using BaseType::operator=; + + // we return only the view so that the user cannot resize it + LocalVectorViewType getLocalVectorView(); + + ConstLocalVectorViewType getLocalVectorView() const; + + + static String getType(); + + virtual String getTypeVirtual() const; + + + /* + * Usual Vector methods follow below. + */ + void addElement( IndexType i, + RealType value ); + + void addElement( IndexType i, + RealType value, + RealType thisElementMultiplicator ); + + template< typename Vector > + DistributedVector& operator-=( const Vector& vector ); + + template< typename Vector > + DistributedVector& operator+=( const Vector& vector ); + + DistributedVector& operator*=( RealType c ); + + DistributedVector& operator/=( RealType c ); + + Real max() const; + + Real min() const; + + Real absMax() const; + + Real absMin() const; + + template< typename ResultType = RealType, typename Real_ > + ResultType lpNorm( const Real_ p ) const; + + template< typename ResultType = RealType > + ResultType sum() const; + + template< typename Vector > + Real differenceMax( const Vector& v ) const; + + template< typename Vector > + Real differenceMin( const Vector& v ) const; + + template< typename Vector > + Real differenceAbsMax( const Vector& v ) const; + + template< typename Vector > + Real differenceAbsMin( const Vector& v ) const; + + template< typename ResultType = RealType, typename Vector, typename Real_ > + ResultType differenceLpNorm( const Vector& v, const Real_ p ) const; + + template< typename ResultType = RealType, typename Vector > + ResultType differenceSum( const Vector& v ) const; + + void scalarMultiplication( Real alpha ); + + //! Computes scalar dot product + template< typename Vector > + Real scalarProduct( const Vector& v ) const; + + //! Computes this = thisMultiplicator * this + alpha * x. + template< typename Vector > + void addVector( const Vector& x, + Real alpha = 1.0, + Real thisMultiplicator = 1.0 ); + + //! Computes this = thisMultiplicator * this + multiplicator1 * v1 + multiplicator2 * v2. + template< typename Vector > + void addVectors( const Vector& v1, + Real multiplicator1, + const Vector& v2, + Real multiplicator2, + Real thisMultiplicator = 1.0 ); + + void computePrefixSum(); + + void computePrefixSum( IndexType begin, IndexType end ); + + void computeExclusivePrefixSum(); + + void computeExclusivePrefixSum( IndexType begin, IndexType end ); +}; + +} // namespace DistributedContainers +} // namespace TNL + +#include "DistributedVector_impl.h" diff --git a/src/TNL/DistributedContainers/DistributedVectorView.h b/src/TNL/DistributedContainers/DistributedVectorView.h new file mode 100644 index 000000000..a3a520f48 --- /dev/null +++ b/src/TNL/DistributedContainers/DistributedVectorView.h @@ -0,0 +1,137 @@ +/*************************************************************************** + DistributedVectorView.h - description + ------------------- + begin : Sep 20, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by: Jakub Klinkovský + +#pragma once + +#include +#include + +namespace TNL { +namespace DistributedContainers { + +template< typename Real, + typename Device = Devices::Host, + typename Index = int, + typename Communicator = Communicators::MpiCommunicator > +class DistributedVectorView +: public DistributedArrayView< Real, Device, Index, Communicator > +{ + using CommunicationGroup = typename Communicator::CommunicationGroup; + using BaseType = DistributedArrayView< Real, Device, Index, Communicator >; + using NonConstReal = typename std::remove_const< Real >::type; +public: + using RealType = Real; + using DeviceType = Device; + using CommunicatorType = Communicator; + using IndexType = Index; + using LocalVectorViewType = Containers::VectorView< Real, Device, Index >; + using ConstLocalVectorViewType = Containers::VectorView< typename std::add_const< Real >::type, Device, Index >; + using HostType = DistributedVectorView< Real, Devices::Host, Index, Communicator >; + using CudaType = DistributedVectorView< Real, Devices::Cuda, Index, Communicator >; + + // inherit all constructors and assignment operators from ArrayView + using BaseType::DistributedArrayView; + using BaseType::operator=; + + LocalVectorViewType getLocalVectorView(); + + ConstLocalVectorViewType getLocalVectorView() const; + + + static String getType(); + + + /* + * Usual Vector methods follow below. + */ + void addElement( IndexType i, + RealType value ); + + void addElement( IndexType i, + RealType value, + RealType thisElementMultiplicator ); + + template< typename Vector > + DistributedVectorView& operator-=( const Vector& vector ); + + template< typename Vector > + DistributedVectorView& operator+=( const Vector& vector ); + + DistributedVectorView& operator*=( RealType c ); + + DistributedVectorView& operator/=( RealType c ); + + NonConstReal max() const; + + NonConstReal min() const; + + NonConstReal absMax() const; + + NonConstReal absMin() const; + + template< typename ResultType = NonConstReal, typename Real_ > + ResultType lpNorm( Real_ p ) const; + + template< typename ResultType = NonConstReal > + ResultType sum() const; + + template< typename Vector > + NonConstReal differenceMax( const Vector& v ) const; + + template< typename Vector > + NonConstReal differenceMin( const Vector& v ) const; + + template< typename Vector > + NonConstReal differenceAbsMax( const Vector& v ) const; + + template< typename Vector > + NonConstReal differenceAbsMin( const Vector& v ) const; + + template< typename ResultType = NonConstReal, typename Vector, typename Real_ > + ResultType differenceLpNorm( const Vector& v, Real_ p ) const; + + template< typename ResultType = NonConstReal, typename Vector > + ResultType differenceSum( const Vector& v ) const; + + void scalarMultiplication( Real alpha ); + + //! Computes scalar dot product + template< typename Vector > + NonConstReal scalarProduct( const Vector& v ) const; + + //! Computes this = thisMultiplicator * this + alpha * x. + template< typename Vector > + void addVector( const Vector& x, + Real alpha = 1.0, + Real thisMultiplicator = 1.0 ); + + //! Computes this = thisMultiplicator * this + multiplicator1 * v1 + multiplicator2 * v2. + template< typename Vector > + void addVectors( const Vector& v1, + Real multiplicator1, + const Vector& v2, + Real multiplicator2, + Real thisMultiplicator = 1.0 ); + + void computePrefixSum(); + + void computePrefixSum( IndexType begin, IndexType end ); + + void computeExclusivePrefixSum(); + + void computeExclusivePrefixSum( IndexType begin, IndexType end ); +}; + +} // namespace DistributedContainers +} // namespace TNL + +#include "DistributedVectorView_impl.h" diff --git a/src/TNL/DistributedContainers/DistributedVectorView_impl.h b/src/TNL/DistributedContainers/DistributedVectorView_impl.h new file mode 100644 index 000000000..f7244d643 --- /dev/null +++ b/src/TNL/DistributedContainers/DistributedVectorView_impl.h @@ -0,0 +1,555 @@ +/*************************************************************************** + DistributedVectorView_impl.h - description + ------------------- + begin : Sep 20, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by: Jakub Klinkovský + +#pragma once + +#include // std::runtime_error + +#include "DistributedVectorView.h" +#include + +namespace TNL { +namespace DistributedContainers { + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +typename DistributedVectorView< Real, Device, Index, Communicator >::LocalVectorViewType +DistributedVectorView< Real, Device, Index, Communicator >:: +getLocalVectorView() +{ + return this->getLocalArrayView(); +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +typename DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType +DistributedVectorView< Real, Device, Index, Communicator >:: +getLocalVectorView() const +{ + return this->getLocalArrayView(); +} + + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +String +DistributedVectorView< Real, Device, Index, Communicator >:: +getType() +{ + return String( "DistributedContainers::DistributedVectorView< " ) + + TNL::getType< Real >() + ", " + + Device::getDeviceType() + ", " + + TNL::getType< Index >() + ", " + + // TODO: communicators don't have a getType method + " >"; +} + + +/* + * Usual Vector methods follow below. + */ + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +void +DistributedVectorView< Real, Device, Index, Communicator >:: +addElement( IndexType i, + RealType value ) +{ + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + const IndexType li = this->getLocalRange().getLocalIndex( i ); + LocalVectorViewType view = getLocalVectorView(); + view.addElement( li, value ); + } +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +void +DistributedVectorView< Real, Device, Index, Communicator >:: +addElement( IndexType i, + RealType value, + RealType thisElementMultiplicator ) +{ + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + const IndexType li = this->getLocalRange().getLocalIndex( i ); + LocalVectorViewType view = getLocalVectorView(); + view.addElement( li, value, thisElementMultiplicator ); + } +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename Vector > +DistributedVectorView< Real, Device, Index, Communicator >& +DistributedVectorView< Real, Device, Index, Communicator >:: +operator-=( const Vector& vector ) +{ + TNL_ASSERT_EQ( this->getSize(), vector.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), vector.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), vector.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + getLocalVectorView() -= vector.getLocalVectorView(); + } + return *this; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename Vector > +DistributedVectorView< Real, Device, Index, Communicator >& +DistributedVectorView< Real, Device, Index, Communicator >:: +operator+=( const Vector& vector ) +{ + TNL_ASSERT_EQ( this->getSize(), vector.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), vector.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), vector.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + getLocalVectorView() += vector.getLocalVectorView(); + } + return *this; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +DistributedVectorView< Real, Device, Index, Communicator >& +DistributedVectorView< Real, Device, Index, Communicator >:: +operator*=( RealType c ) +{ + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + getLocalVectorView() *= c; + } + return *this; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +DistributedVectorView< Real, Device, Index, Communicator >& +DistributedVectorView< Real, Device, Index, Communicator >:: +operator/=( RealType c ) +{ + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + getLocalVectorView() /= c; + } + return *this; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +typename DistributedVectorView< Real, Device, Index, Communicator >::NonConstReal +DistributedVectorView< Real, Device, Index, Communicator >:: +max() const +{ + const auto group = this->getCommunicationGroup(); + NonConstReal result = Containers::Algorithms::ParallelReductionMax< Real >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const Real localResult = getLocalVectorView().max(); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MAX, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +typename DistributedVectorView< Real, Device, Index, Communicator >::NonConstReal +DistributedVectorView< Real, Device, Index, Communicator >:: +min() const +{ + const auto group = this->getCommunicationGroup(); + NonConstReal result = Containers::Algorithms::ParallelReductionMin< Real >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const Real localResult = getLocalVectorView().min(); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MIN, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +typename DistributedVectorView< Real, Device, Index, Communicator >::NonConstReal +DistributedVectorView< Real, Device, Index, Communicator >:: +absMax() const +{ + const auto group = this->getCommunicationGroup(); + NonConstReal result = Containers::Algorithms::ParallelReductionAbsMax< Real >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const Real localResult = getLocalVectorView().absMax(); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MAX, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +typename DistributedVectorView< Real, Device, Index, Communicator >::NonConstReal +DistributedVectorView< Real, Device, Index, Communicator >:: +absMin() const +{ + const auto group = this->getCommunicationGroup(); + NonConstReal result = Containers::Algorithms::ParallelReductionAbsMin< Real >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const Real localResult = getLocalVectorView().absMin(); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MIN, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename ResultType, typename Real_ > +ResultType +DistributedVectorView< Real, Device, Index, Communicator >:: +lpNorm( const Real_ p ) const +{ + const auto group = this->getCommunicationGroup(); + ResultType result = Containers::Algorithms::ParallelReductionLpNorm< Real, ResultType, Real_ >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const ResultType localResult = std::pow( getLocalVectorView().lpNorm( p ), p ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, group ); + result = std::pow( result, 1.0 / p ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename ResultType > +ResultType +DistributedVectorView< Real, Device, Index, Communicator >:: +sum() const +{ + const auto group = this->getCommunicationGroup(); + ResultType result = Containers::Algorithms::ParallelReductionSum< Real, ResultType >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const ResultType localResult = getLocalVectorView().sum(); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename Vector > +typename DistributedVectorView< Real, Device, Index, Communicator >::NonConstReal +DistributedVectorView< Real, Device, Index, Communicator >:: +differenceMax( const Vector& v ) const +{ + TNL_ASSERT_EQ( this->getSize(), v.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), v.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), v.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + + const auto group = this->getCommunicationGroup(); + NonConstReal result = Containers::Algorithms::ParallelReductionDiffMax< Real, typename Vector::RealType >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const Real localResult = getLocalVectorView().differenceMax( v.getLocalVectorView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MAX, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename Vector > +typename DistributedVectorView< Real, Device, Index, Communicator >::NonConstReal +DistributedVectorView< Real, Device, Index, Communicator >:: +differenceMin( const Vector& v ) const +{ + TNL_ASSERT_EQ( this->getSize(), v.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), v.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), v.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + + const auto group = this->getCommunicationGroup(); + NonConstReal result = Containers::Algorithms::ParallelReductionDiffMin< Real, typename Vector::RealType >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const Real localResult = getLocalVectorView().differenceMin( v.getLocalVectorView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MIN, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename Vector > +typename DistributedVectorView< Real, Device, Index, Communicator >::NonConstReal +DistributedVectorView< Real, Device, Index, Communicator >:: +differenceAbsMax( const Vector& v ) const +{ + TNL_ASSERT_EQ( this->getSize(), v.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), v.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), v.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + + const auto group = this->getCommunicationGroup(); + NonConstReal result = Containers::Algorithms::ParallelReductionDiffAbsMax< Real, typename Vector::RealType >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const Real localResult = getLocalVectorView().differenceAbsMax( v.getLocalVectorView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MAX, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename Vector > +typename DistributedVectorView< Real, Device, Index, Communicator >::NonConstReal +DistributedVectorView< Real, Device, Index, Communicator >:: +differenceAbsMin( const Vector& v ) const +{ + TNL_ASSERT_EQ( this->getSize(), v.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), v.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), v.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + + const auto group = this->getCommunicationGroup(); + NonConstReal result = Containers::Algorithms::ParallelReductionDiffAbsMin< Real, typename Vector::RealType >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const Real localResult = getLocalVectorView().differenceAbsMin( v.getLocalVectorView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MIN, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename ResultType, typename Vector, typename Real_ > +ResultType +DistributedVectorView< Real, Device, Index, Communicator >:: +differenceLpNorm( const Vector& v, const Real_ p ) const +{ + const auto group = this->getCommunicationGroup(); + ResultType result = Containers::Algorithms::ParallelReductionDiffLpNorm< Real, typename Vector::RealType, ResultType, Real_ >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const ResultType localResult = std::pow( getLocalVectorView().differenceLpNorm( v.getLocalVectorView(), p ), p ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, group ); + result = std::pow( result, 1.0 / p ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename ResultType, typename Vector > +ResultType +DistributedVectorView< Real, Device, Index, Communicator >:: +differenceSum( const Vector& v ) const +{ + TNL_ASSERT_EQ( this->getSize(), v.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), v.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), v.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + + const auto group = this->getCommunicationGroup(); + ResultType result = Containers::Algorithms::ParallelReductionDiffSum< Real, typename Vector::RealType, ResultType >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const ResultType localResult = getLocalVectorView().differenceSum( v.getLocalVectorView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +void +DistributedVectorView< Real, Device, Index, Communicator >:: +scalarMultiplication( Real alpha ) +{ + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + getLocalVectorView().scalarMultiplication( alpha ); + } +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename Vector > +typename DistributedVectorView< Real, Device, Index, Communicator >::NonConstReal +DistributedVectorView< Real, Device, Index, Communicator >:: +scalarProduct( const Vector& v ) const +{ + const auto group = this->getCommunicationGroup(); + NonConstReal result = Containers::Algorithms::ParallelReductionScalarProduct< Real, typename Vector::RealType >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const Real localResult = getLocalVectorView().scalarProduct( v.getLocalVectorView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename Vector > +void +DistributedVectorView< Real, Device, Index, Communicator >:: +addVector( const Vector& x, + Real alpha, + Real thisMultiplicator ) +{ + TNL_ASSERT_EQ( this->getSize(), x.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), x.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), x.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + getLocalVectorView().addVector( x.getLocalVectorView(), alpha, thisMultiplicator ); + } +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename Vector > +void +DistributedVectorView< Real, Device, Index, Communicator >:: +addVectors( const Vector& v1, + Real multiplicator1, + const Vector& v2, + Real multiplicator2, + Real thisMultiplicator ) +{ + TNL_ASSERT_EQ( this->getSize(), v1.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), v1.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), v1.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + TNL_ASSERT_EQ( this->getSize(), v2.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), v2.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), v2.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + getLocalVectorView().addVectors( v1.getLocalVectorView(), + multiplicator1, + v2.getLocalVectorView(), + multiplicator2, + thisMultiplicator ); + } +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +void +DistributedVectorView< Real, Device, Index, Communicator >:: +computePrefixSum() +{ + throw std::runtime_error("Distributed prefix sum is not implemented yet."); +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +void +DistributedVectorView< Real, Device, Index, Communicator >:: +computePrefixSum( IndexType begin, IndexType end ) +{ + throw std::runtime_error("Distributed prefix sum is not implemented yet."); +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +void +DistributedVectorView< Real, Device, Index, Communicator >:: +computeExclusivePrefixSum() +{ + throw std::runtime_error("Distributed prefix sum is not implemented yet."); +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +void +DistributedVectorView< Real, Device, Index, Communicator >:: +computeExclusivePrefixSum( IndexType begin, IndexType end ) +{ + throw std::runtime_error("Distributed prefix sum is not implemented yet."); +} + +} // namespace DistributedContainers +} // namespace TNL diff --git a/src/TNL/DistributedContainers/DistributedVector_impl.h b/src/TNL/DistributedContainers/DistributedVector_impl.h new file mode 100644 index 000000000..db93d322b --- /dev/null +++ b/src/TNL/DistributedContainers/DistributedVector_impl.h @@ -0,0 +1,566 @@ +/*************************************************************************** + DistributedVector_impl.h - description + ------------------- + begin : Sep 7, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by: Jakub Klinkovský + +#pragma once + +#include // std::runtime_error + +#include "DistributedVector.h" +#include + +namespace TNL { +namespace DistributedContainers { + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +typename DistributedVector< Real, Device, Index, Communicator >::LocalVectorViewType +DistributedVector< Real, Device, Index, Communicator >:: +getLocalVectorView() +{ + return this->getLocalArrayView(); +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +typename DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType +DistributedVector< Real, Device, Index, Communicator >:: +getLocalVectorView() const +{ + return this->getLocalArrayView(); +} + + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +String +DistributedVector< Real, Device, Index, Communicator >:: +getType() +{ + return String( "DistributedContainers::DistributedVector< " ) + + TNL::getType< Real >() + ", " + + Device::getDeviceType() + ", " + + TNL::getType< Index >() + ", " + + // TODO: communicators don't have a getType method + " >"; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +String +DistributedVector< Real, Device, Index, Communicator >:: +getTypeVirtual() const +{ + return getType(); +} + + +/* + * Usual Vector methods follow below. + */ + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +void +DistributedVector< Real, Device, Index, Communicator >:: +addElement( IndexType i, + RealType value ) +{ + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + const IndexType li = this->getLocalRange().getLocalIndex( i ); + LocalVectorViewType view = getLocalVectorView(); + view.addElement( li, value ); + } +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +void +DistributedVector< Real, Device, Index, Communicator >:: +addElement( IndexType i, + RealType value, + RealType thisElementMultiplicator ) +{ + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + const IndexType li = this->getLocalRange().getLocalIndex( i ); + LocalVectorViewType view = getLocalVectorView(); + view.addElement( li, value, thisElementMultiplicator ); + } +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename Vector > +DistributedVector< Real, Device, Index, Communicator >& +DistributedVector< Real, Device, Index, Communicator >:: +operator-=( const Vector& vector ) +{ + TNL_ASSERT_EQ( this->getSize(), vector.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), vector.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), vector.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + getLocalVectorView() -= vector.getLocalVectorView(); + } + return *this; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename Vector > +DistributedVector< Real, Device, Index, Communicator >& +DistributedVector< Real, Device, Index, Communicator >:: +operator+=( const Vector& vector ) +{ + TNL_ASSERT_EQ( this->getSize(), vector.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), vector.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), vector.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + getLocalVectorView() += vector.getLocalVectorView(); + } + return *this; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +DistributedVector< Real, Device, Index, Communicator >& +DistributedVector< Real, Device, Index, Communicator >:: +operator*=( RealType c ) +{ + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + getLocalVectorView() *= c; + } + return *this; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +DistributedVector< Real, Device, Index, Communicator >& +DistributedVector< Real, Device, Index, Communicator >:: +operator/=( RealType c ) +{ + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + getLocalVectorView() /= c; + } + return *this; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +Real +DistributedVector< Real, Device, Index, Communicator >:: +max() const +{ + const auto group = this->getCommunicationGroup(); + Real result = Containers::Algorithms::ParallelReductionMax< Real >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const Real localResult = getLocalVectorView().max(); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MAX, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +Real +DistributedVector< Real, Device, Index, Communicator >:: +min() const +{ + const auto group = this->getCommunicationGroup(); + Real result = Containers::Algorithms::ParallelReductionMin< Real >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const Real localResult = getLocalVectorView().min(); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MIN, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +Real +DistributedVector< Real, Device, Index, Communicator >:: +absMax() const +{ + const auto group = this->getCommunicationGroup(); + Real result = Containers::Algorithms::ParallelReductionAbsMax< Real >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const Real localResult = getLocalVectorView().absMax(); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MAX, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +Real +DistributedVector< Real, Device, Index, Communicator >:: +absMin() const +{ + const auto group = this->getCommunicationGroup(); + Real result = Containers::Algorithms::ParallelReductionAbsMin< Real >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const Real localResult = getLocalVectorView().absMin(); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MIN, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename ResultType, typename Real_ > +ResultType +DistributedVector< Real, Device, Index, Communicator >:: +lpNorm( const Real_ p ) const +{ + const auto group = this->getCommunicationGroup(); + ResultType result = Containers::Algorithms::ParallelReductionLpNorm< Real, ResultType, Real_ >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const ResultType localResult = std::pow( getLocalVectorView().lpNorm( p ), p ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, group ); + result = std::pow( result, 1.0 / p ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename ResultType > +ResultType +DistributedVector< Real, Device, Index, Communicator >:: +sum() const +{ + const auto group = this->getCommunicationGroup(); + ResultType result = Containers::Algorithms::ParallelReductionSum< Real, ResultType >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const ResultType localResult = getLocalVectorView().sum(); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename Vector > +Real +DistributedVector< Real, Device, Index, Communicator >:: +differenceMax( const Vector& v ) const +{ + TNL_ASSERT_EQ( this->getSize(), v.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), v.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), v.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + + const auto group = this->getCommunicationGroup(); + Real result = Containers::Algorithms::ParallelReductionDiffMax< Real, typename Vector::RealType >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const Real localResult = getLocalVectorView().differenceMax( v.getLocalVectorView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MAX, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename Vector > +Real +DistributedVector< Real, Device, Index, Communicator >:: +differenceMin( const Vector& v ) const +{ + TNL_ASSERT_EQ( this->getSize(), v.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), v.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), v.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + + const auto group = this->getCommunicationGroup(); + Real result = Containers::Algorithms::ParallelReductionDiffMin< Real, typename Vector::RealType >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const Real localResult = getLocalVectorView().differenceMin( v.getLocalVectorView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MIN, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename Vector > +Real +DistributedVector< Real, Device, Index, Communicator >:: +differenceAbsMax( const Vector& v ) const +{ + TNL_ASSERT_EQ( this->getSize(), v.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), v.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), v.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + + const auto group = this->getCommunicationGroup(); + Real result = Containers::Algorithms::ParallelReductionDiffAbsMax< Real, typename Vector::RealType >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const Real localResult = getLocalVectorView().differenceAbsMax( v.getLocalVectorView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MAX, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename Vector > +Real +DistributedVector< Real, Device, Index, Communicator >:: +differenceAbsMin( const Vector& v ) const +{ + TNL_ASSERT_EQ( this->getSize(), v.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), v.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), v.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + + const auto group = this->getCommunicationGroup(); + Real result = Containers::Algorithms::ParallelReductionDiffAbsMin< Real, typename Vector::RealType >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const Real localResult = getLocalVectorView().differenceAbsMin( v.getLocalVectorView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MIN, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename ResultType, typename Vector, typename Real_ > +ResultType +DistributedVector< Real, Device, Index, Communicator >:: +differenceLpNorm( const Vector& v, const Real_ p ) const +{ + const auto group = this->getCommunicationGroup(); + ResultType result = Containers::Algorithms::ParallelReductionDiffLpNorm< Real, typename Vector::RealType, ResultType, Real_ >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const ResultType localResult = std::pow( getLocalVectorView().differenceLpNorm( v.getLocalVectorView(), p ), p ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, group ); + result = std::pow( result, 1.0 / p ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename ResultType, typename Vector > +ResultType +DistributedVector< Real, Device, Index, Communicator >:: +differenceSum( const Vector& v ) const +{ + TNL_ASSERT_EQ( this->getSize(), v.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), v.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), v.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + + const auto group = this->getCommunicationGroup(); + ResultType result = Containers::Algorithms::ParallelReductionDiffSum< Real, typename Vector::RealType, ResultType >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const ResultType localResult = getLocalVectorView().differenceSum( v.getLocalVectorView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +void +DistributedVector< Real, Device, Index, Communicator >:: +scalarMultiplication( Real alpha ) +{ + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + getLocalVectorView().scalarMultiplication( alpha ); + } +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename Vector > +Real +DistributedVector< Real, Device, Index, Communicator >:: +scalarProduct( const Vector& v ) const +{ + const auto group = this->getCommunicationGroup(); + Real result = Containers::Algorithms::ParallelReductionScalarProduct< Real, typename Vector::RealType >::initialValue(); + if( group != CommunicatorType::NullGroup ) { + const Real localResult = getLocalVectorView().scalarProduct( v.getLocalVectorView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, group ); + } + return result; +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename Vector > +void +DistributedVector< Real, Device, Index, Communicator >:: +addVector( const Vector& x, + Real alpha, + Real thisMultiplicator ) +{ + TNL_ASSERT_EQ( this->getSize(), x.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), x.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), x.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + getLocalVectorView().addVector( x.getLocalVectorView(), alpha, thisMultiplicator ); + } +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > + template< typename Vector > +void +DistributedVector< Real, Device, Index, Communicator >:: +addVectors( const Vector& v1, + Real multiplicator1, + const Vector& v2, + Real multiplicator2, + Real thisMultiplicator ) +{ + TNL_ASSERT_EQ( this->getSize(), v1.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), v1.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), v1.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + TNL_ASSERT_EQ( this->getSize(), v2.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), v2.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), v2.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + getLocalVectorView().addVectors( v1.getLocalVectorView(), + multiplicator1, + v2.getLocalVectorView(), + multiplicator2, + thisMultiplicator ); + } +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +void +DistributedVector< Real, Device, Index, Communicator >:: +computePrefixSum() +{ + throw std::runtime_error("Distributed prefix sum is not implemented yet."); +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +void +DistributedVector< Real, Device, Index, Communicator >:: +computePrefixSum( IndexType begin, IndexType end ) +{ + throw std::runtime_error("Distributed prefix sum is not implemented yet."); +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +void +DistributedVector< Real, Device, Index, Communicator >:: +computeExclusivePrefixSum() +{ + throw std::runtime_error("Distributed prefix sum is not implemented yet."); +} + +template< typename Real, + typename Device, + typename Index, + typename Communicator > +void +DistributedVector< Real, Device, Index, Communicator >:: +computeExclusivePrefixSum( IndexType begin, IndexType end ) +{ + throw std::runtime_error("Distributed prefix sum is not implemented yet."); +} + +} // namespace DistributedContainers +} // namespace TNL diff --git a/src/TNL/DistributedContainers/Partitioner.h b/src/TNL/DistributedContainers/Partitioner.h new file mode 100644 index 000000000..3c8cace6f --- /dev/null +++ b/src/TNL/DistributedContainers/Partitioner.h @@ -0,0 +1,73 @@ +/*************************************************************************** + Partitioner.h - description + ------------------- + begin : Sep 6, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by: Jakub Klinkovský + +#pragma once + +#include "Subrange.h" + +#include + +namespace TNL { +namespace DistributedContainers { + +template< typename Index, typename Communicator > +class Partitioner +{ + using CommunicationGroup = typename Communicator::CommunicationGroup; +public: + using SubrangeType = Subrange< Index >; + + static SubrangeType splitRange( Index globalSize, CommunicationGroup group ) + { + if( group != Communicator::NullGroup ) { + const int rank = Communicator::GetRank( group ); + const int partitions = Communicator::GetSize( group ); + const Index begin = min( globalSize, rank * globalSize / partitions ); + const Index end = min( globalSize, (rank + 1) * globalSize / partitions ); + return SubrangeType( begin, end ); + } + else + return SubrangeType( 0, 0 ); + } + + // Gets the owner of given global index. + __cuda_callable__ + static int getOwner( Index i, Index globalSize, int partitions ) + { + return i * partitions / globalSize; + } + + // Gets the offset of data for given rank. + __cuda_callable__ + static Index getOffset( Index globalSize, int rank, int partitions ) + { + return rank * globalSize / partitions; + } + + // Gets the size of data assigned to given rank. + __cuda_callable__ + static Index getSizeForRank( Index globalSize, int rank, int partitions ) + { + const Index begin = min( globalSize, rank * globalSize / partitions ); + const Index end = min( globalSize, (rank + 1) * globalSize / partitions ); + return end - begin; + } +}; + +// TODO: +// - partitioner in deal.II stores also ghost indices: +// https://www.dealii.org/8.4.0/doxygen/deal.II/classUtilities_1_1MPI_1_1Partitioner.html +// - ghost indices are stored in a general IndexMap class (based on collection of subranges): +// https://www.dealii.org/8.4.0/doxygen/deal.II/classIndexSet.html + +} // namespace DistributedContainers +} // namespace TNL diff --git a/src/TNL/DistributedContainers/Subrange.h b/src/TNL/DistributedContainers/Subrange.h new file mode 100644 index 000000000..8cff45b49 --- /dev/null +++ b/src/TNL/DistributedContainers/Subrange.h @@ -0,0 +1,123 @@ +/*************************************************************************** + Subrange.h - description + ------------------- + begin : Sep 6, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by: Jakub Klinkovský + +#pragma once + +#include +#include +#include + +namespace TNL { +namespace DistributedContainers { + +// Specifies a subrange [begin, end) of a range [0, gloablSize). +template< typename Index > +class Subrange +{ +public: + using IndexType = Index; + + __cuda_callable__ + Subrange() = default; + + __cuda_callable__ + Subrange( Index begin, Index end ) + { + setSubrange( begin, end ); + } + + // Sets the local subrange and global range size. + __cuda_callable__ + void setSubrange( Index begin, Index end ) + { + TNL_ASSERT_LE( begin, end, "begin must be before end" ); + TNL_ASSERT_GE( begin, 0, "begin must be non-negative" ); + this->begin = begin; + this->end = end; + } + + __cuda_callable__ + void reset() + { + begin = 0; + end = 0; + } + + static String getType() + { + return "Subrange< " + TNL::getType< Index >() + " >"; + } + + // Checks if a global index is in the set of local indices. + __cuda_callable__ + bool isLocal( Index i ) const + { + return begin <= i && i < end; + } + + // Gets the begin of the subrange. + __cuda_callable__ + Index getBegin() const + { + return begin; + } + + // Gets the begin of the subrange. + __cuda_callable__ + Index getEnd() const + { + return end; + } + + // Gets number of local indices. + __cuda_callable__ + Index getSize() const + { + return end - begin; + } + + // Gets local index for given global index. + __cuda_callable__ + Index getLocalIndex( Index i ) const + { + TNL_ASSERT_GE( i, getBegin(), "Given global index was not found in the local index set." ); + TNL_ASSERT_LT( i, getEnd(), "Given global index was not found in the local index set." ); + return i - begin; + } + + // Gets global index for given local index. + __cuda_callable__ + Index getGlobalIndex( Index i ) const + { + TNL_ASSERT_GE( i, 0, "Given local index was not found in the local index set." ); + TNL_ASSERT_LT( i, getSize(), "Given local index was not found in the local index set." ); + return i + begin; + } + + bool operator==( const Subrange& other ) const + { + return begin == other.begin && + end == other.end; + } + + bool operator!=( const Subrange& other ) const + { + return ! (*this == other); + } + +protected: + Index begin = 0; + Index end = 0; +}; + +} // namespace DistributedContainers +} // namespace TNL diff --git a/src/TNL/Doxyfile b/src/TNL/Doxyfile deleted file mode 100644 index 4fb5d22f9..000000000 --- a/src/TNL/Doxyfile +++ /dev/null @@ -1,1514 +0,0 @@ -# Doxyfile 1.6.1 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = tnl - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = ../Release/src - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = YES - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# 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 = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = - -# 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 = - -# 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. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = NO - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 3 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it parses. -# With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this tag. -# The format is ext=language, where ext is a file extension, and language is one of -# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, -# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat -# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), -# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. - -EXTENSION_MAPPING = - -# 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 = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen to replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. - -TYPEDEF_HIDES_STRUCT = NO - -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penality. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will rougly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols - -SYMBOL_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespace are hidden. - -EXTRACT_ANON_NSPACES = NO - -# 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 = NO - -# 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 = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# 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 = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = 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. - -SHOW_DIRECTORIES = NO - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by -# doxygen. The layout file controls the global structure of the generated output files -# in an output format independent way. The create the layout file that represents -# doxygen's defaults, run doxygen with the -l option. You can optionally specify a -# file name after the option, if omitted DoxygenLayout.xml will be used as the name -# of the layout file. - -LAYOUT_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# 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 = - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 - -FILE_PATTERNS = - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# 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 = - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# 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 = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# 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 = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. - -REFERENCES_LINK_SOURCE = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = NO - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# 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. - -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. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = NO - -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. - -GENERATE_DOCSET = NO - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. - -CHM_INDEX_ENCODING = - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER -# are set, an additional index file will be generated that can be used as input for -# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated -# HTML documentation. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace - -QHP_NAMESPACE = - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders - -QHP_VIRTUAL_FOLDER = doc - -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. -# For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see -# Qt Help Project / Custom Filters. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's -# filter section matches. -# Qt Help Project / Filter Attributes. - -QHP_SECT_FILTER_ATTRS = - -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. - -QHG_LOCATION = - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. - -GENERATE_TREEVIEW = NO - -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. - -USE_INLINE_TREES = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. - -FORMULA_FONTSIZE = 10 - -# When the SEARCHENGINE tag is enable doxygen will generate a search box for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP) or Qt help (GENERATE_QHP) -# there is already a search function so this one should typically -# be disabled. - -SEARCHENGINE = YES - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = YES - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = YES - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = YES - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -# If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER. - -LATEX_SOURCE_CODE = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. -# This is useful -# if you want to understand what is going on. -# On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# 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 = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more -# powerful graphs. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = NO - -# By default doxygen will write a font called FreeSans.ttf to the output -# directory and reference it in all dot files that doxygen generates. This -# font does not include all possible unicode characters however, so when you need -# these (or just want a differently looking font) you can specify the font name -# using DOT_FONTNAME. You need need to make sure dot is able to find the font, -# which can be done by putting it in a standard location or by setting the -# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory -# containing the font. - -DOT_FONTNAME = FreeSans - -# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. -# The default size is 10pt. - -DOT_FONTSIZE = 10 - -# By default doxygen will tell dot to use the output directory to look for the -# FreeSans.ttf font (which doxygen will put there itself). If you specify a -# different font using DOT_FONTNAME you can set the path where dot -# can find it using this tag. - -DOT_FONTPATH = - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = NO - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. - -CALLER_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of -# a graph (i.e. they become hard to read). - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = YES - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES diff --git a/src/TNL/Matrices/CMakeLists.txt b/src/TNL/Matrices/CMakeLists.txt index 82c8924bf..f8cc64584 100644 --- a/src/TNL/Matrices/CMakeLists.txt +++ b/src/TNL/Matrices/CMakeLists.txt @@ -14,6 +14,8 @@ SET( headers AdEllpack.h Multidiagonal_impl.h Sparse.h Sparse_impl.h + SparseOperations.h + SparseOperations_impl.h Ellpack.h Ellpack_impl.h SlicedEllpack.h @@ -40,17 +42,4 @@ SET( headers AdEllpack.h MultidiagonalRow.h MultidiagonalRow_impl.h ) -SET( CURRENT_DIR ${CMAKE_SOURCE_DIR}/src/TNL/Matrices ) -set( common_SOURCES ) - -SET( tnl_matrices_SOURCES - ${common_SOURCES} - PARENT_SCOPE ) - -if( BUILD_CUDA ) - SET( tnl_matrices_CUDA__SOURCES - ${common_SOURCES} - PARENT_SCOPE ) -endif() - INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Matrices ) diff --git a/src/TNL/Matrices/Sparse.h b/src/TNL/Matrices/Sparse.h index 110dd7a40..2ee49219e 100644 --- a/src/TNL/Matrices/Sparse.h +++ b/src/TNL/Matrices/Sparse.h @@ -14,7 +14,7 @@ #include namespace TNL { -namespace Matrices { +namespace Matrices { template< typename Real, typename Device, @@ -62,14 +62,8 @@ class Sparse : public Matrix< Real, Device, Index > Index maxRowLength; }; - -// This cannot be a method of the Sparse class, because the implementation uses -// methods (marked with __cuda_callable__) which are defined only on the -// subclasses, but are not virtual methods of Sparse. -template< typename Matrix1, typename Matrix2 > -void copySparseMatrix( Matrix1& A, const Matrix2& B ); - } // namespace Matrices } // namespace TNL #include +#include diff --git a/src/TNL/Matrices/SparseOperations.h b/src/TNL/Matrices/SparseOperations.h new file mode 100644 index 000000000..07aecc3cd --- /dev/null +++ b/src/TNL/Matrices/SparseOperations.h @@ -0,0 +1,51 @@ +/*************************************************************************** + SparseOperations.h - description + ------------------- + begin : Oct 4, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by: Jakub Klinkovský + +// Note that these functions cannot be methods of the Sparse class, because +// their implementation uses methods (marked with __cuda_callable__) which are +// defined only on the subclasses, but are not virtual methods of Sparse. + +#pragma once + +namespace TNL { +namespace Matrices { + +template< typename Matrix1, typename Matrix2 > +void copySparseMatrix( Matrix1& A, const Matrix2& B ); + +// NOTE: if `has_symmetric_pattern`, the sparsity pattern of `A` is assumed +// to be symmetric and it is just copied to `B`. Otherwise, the sparsity +// pattern of `A^T + A` is copied to `B`. +template< typename Matrix, typename AdjacencyMatrix > +void +copyAdjacencyStructure( const Matrix& A, AdjacencyMatrix& B, + bool has_symmetric_pattern = false, + bool ignore_diagonal = true ); + +// Applies a permutation to the rows of a sparse matrix and its inverse +// permutation to the columns of the matrix, i.e. A_perm = P*A*P^{-1}, where +// P is the permutation matrix represented by the perm vector and P^{-1} is the +// inverse permutation represented by the iperm vector. +template< typename Matrix1, typename Matrix2, typename PermutationArray > +void +reorderSparseMatrix( const Matrix1& A, Matrix2& A_perm, + const PermutationArray& perm, const PermutationArray& iperm ); + +// TODO: the method does not belong here, but there is no better place... +template< typename Array1, typename Array2, typename PermutationArray > +void +reorderArray( const Array1& src, Array2& dest, const PermutationArray& perm ); + +} // namespace Matrices +} // namespace TNL + +#include "SparseOperations_impl.h" diff --git a/src/TNL/Matrices/SparseOperations_impl.h b/src/TNL/Matrices/SparseOperations_impl.h new file mode 100644 index 000000000..ccc8930f9 --- /dev/null +++ b/src/TNL/Matrices/SparseOperations_impl.h @@ -0,0 +1,364 @@ +/*************************************************************************** + SparseOperations_impl.h - description + ------------------- + begin : Oct 4, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by: Jakub Klinkovský + +#pragma once + +#include +#include +#include + +#include +#include + +namespace TNL { +namespace Matrices { + +#ifdef HAVE_CUDA +template< typename Vector, typename Matrix > +__global__ void +SparseMatrixSetRowLengthsVectorKernel( Vector* rowLengths, + const Matrix* matrix, + typename Matrix::IndexType rows, + typename Matrix::IndexType cols ) +{ + using IndexType = typename Matrix::IndexType; + + IndexType rowIdx = blockIdx.x * blockDim.x + threadIdx.x; + const IndexType gridSize = blockDim.x * gridDim.x; + + while( rowIdx < rows ) { + const auto max_length = matrix->getRowLengthFast( rowIdx ); + const auto row = matrix->getRow( rowIdx ); + IndexType length = 0; + for( IndexType c_j = 0; c_j < max_length; c_j++ ) + if( row.getElementColumn( c_j ) < cols ) + length++; + else + break; + rowLengths[ rowIdx ] = length; + rowIdx += gridSize; + } +} + +template< typename Matrix1, typename Matrix2 > +__global__ void +SparseMatrixCopyKernel( Matrix1* A, + const Matrix2* B, + const typename Matrix2::IndexType* rowLengths, + typename Matrix2::IndexType rows ) +{ + using IndexType = typename Matrix2::IndexType; + + IndexType rowIdx = blockIdx.x * blockDim.x + threadIdx.x; + const IndexType gridSize = blockDim.x * gridDim.x; + + while( rowIdx < rows ) { + const auto length = rowLengths[ rowIdx ]; + const auto rowB = B->getRow( rowIdx ); + auto rowA = A->getRow( rowIdx ); + for( IndexType c = 0; c < length; c++ ) + rowA.setElement( c, rowB.getElementColumn( c ), rowB.getElementValue( c ) ); + rowIdx += gridSize; + } +} +#endif + +// copy on the same device +template< typename Matrix1, + typename Matrix2 > +typename std::enable_if< std::is_same< typename Matrix1::DeviceType, typename Matrix2::DeviceType >::value >::type +copySparseMatrix_impl( Matrix1& A, const Matrix2& B ) +{ + static_assert( std::is_same< typename Matrix1::RealType, typename Matrix2::RealType >::value, + "The matrices must have the same RealType." ); + static_assert( std::is_same< typename Matrix1::DeviceType, typename Matrix2::DeviceType >::value, + "The matrices must be allocated on the same device." ); + static_assert( std::is_same< typename Matrix1::IndexType, typename Matrix2::IndexType >::value, + "The matrices must have the same IndexType." ); + + using RealType = typename Matrix1::RealType; + using DeviceType = typename Matrix1::DeviceType; + using IndexType = typename Matrix1::IndexType; + + const IndexType rows = B.getRows(); + const IndexType cols = B.getColumns(); + + A.setDimensions( rows, cols ); + + if( std::is_same< DeviceType, Devices::Host >::value ) { + // set row lengths + typename Matrix1::CompressedRowLengthsVector rowLengths; + rowLengths.setSize( rows ); +#ifdef HAVE_OPENMP +#pragma omp parallel for if( Devices::Host::isOMPEnabled() ) +#endif + for( IndexType i = 0; i < rows; i++ ) { + const auto max_length = B.getRowLength( i ); + const auto row = B.getRow( i ); + IndexType length = 0; + for( IndexType c_j = 0; c_j < max_length; c_j++ ) + if( row.getElementColumn( c_j ) < cols ) + length++; + else + break; + rowLengths[ i ] = length; + } + A.setCompressedRowLengths( rowLengths ); + +#ifdef HAVE_OPENMP +#pragma omp parallel for if( Devices::Host::isOMPEnabled() ) +#endif + for( IndexType i = 0; i < rows; i++ ) { + const auto length = rowLengths[ i ]; + const auto rowB = B.getRow( i ); + auto rowA = A.getRow( i ); + for( IndexType c = 0; c < length; c++ ) + rowA.setElement( c, rowB.getElementColumn( c ), rowB.getElementValue( c ) ); + } + } + + if( std::is_same< DeviceType, Devices::Cuda >::value ) { +#ifdef HAVE_CUDA + dim3 blockSize( 256 ); + dim3 gridSize; + const IndexType desGridSize = 32 * Devices::CudaDeviceInfo::getCudaMultiprocessors( Devices::CudaDeviceInfo::getActiveDevice() ); + gridSize.x = min( desGridSize, Devices::Cuda::getNumberOfBlocks( rows, blockSize.x ) ); + + typename Matrix1::CompressedRowLengthsVector rowLengths; + rowLengths.setSize( rows ); + + Pointers::DevicePointer< Matrix1 > Apointer( A ); + const Pointers::DevicePointer< const Matrix2 > Bpointer( B ); + + // set row lengths + Devices::Cuda::synchronizeDevice(); + SparseMatrixSetRowLengthsVectorKernel<<< gridSize, blockSize >>>( + rowLengths.getData(), + &Bpointer.template getData< TNL::Devices::Cuda >(), + rows, + cols ); + TNL_CHECK_CUDA_DEVICE; + Apointer->setCompressedRowLengths( rowLengths ); + + // copy rows + Devices::Cuda::synchronizeDevice(); + SparseMatrixCopyKernel<<< gridSize, blockSize >>>( + &Apointer.template modifyData< TNL::Devices::Cuda >(), + &Bpointer.template getData< TNL::Devices::Cuda >(), + rowLengths.getData(), + rows ); + TNL_CHECK_CUDA_DEVICE; +#else + throw Exceptions::CudaSupportMissing(); +#endif + } +} + +// cross-device copy (host -> gpu) +template< typename Matrix1, + typename Matrix2 > +typename std::enable_if< ! std::is_same< typename Matrix1::DeviceType, typename Matrix2::DeviceType >::value && + std::is_same< typename Matrix2::DeviceType, Devices::Host >::value >::type +copySparseMatrix_impl( Matrix1& A, const Matrix2& B ) +{ + typename Matrix2::CudaType B_tmp; + B_tmp = B; + copySparseMatrix_impl( A, B_tmp ); +} + +// cross-device copy (gpu -> host) +template< typename Matrix1, + typename Matrix2 > +typename std::enable_if< ! std::is_same< typename Matrix1::DeviceType, typename Matrix2::DeviceType >::value && + std::is_same< typename Matrix2::DeviceType, Devices::Cuda >::value >::type +copySparseMatrix_impl( Matrix1& A, const Matrix2& B ) +{ + typename Matrix1::CudaType A_tmp; + copySparseMatrix_impl( A_tmp, B ); + A = A_tmp; +} + +template< typename Matrix1, typename Matrix2 > +void +copySparseMatrix( Matrix1& A, const Matrix2& B ) +{ + copySparseMatrix_impl( A, B ); +} + + +template< typename Matrix, typename AdjacencyMatrix > +void +copyAdjacencyStructure( const Matrix& A, AdjacencyMatrix& B, + bool has_symmetric_pattern, + bool ignore_diagonal ) +{ + static_assert( std::is_same< typename Matrix::DeviceType, Devices::Host >::value, + "The function is not implemented for CUDA matrices - it would require atomic insertions " + "of elements into the sparse format." ); + static_assert( std::is_same< typename Matrix::DeviceType, typename AdjacencyMatrix::DeviceType >::value, + "The matrices must be allocated on the same device." ); + static_assert( std::is_same< typename Matrix::IndexType, typename AdjacencyMatrix::IndexType >::value, + "The matrices must have the same IndexType." ); +// static_assert( std::is_same< typename AdjacencyMatrix::RealType, bool >::value, +// "The RealType of the adjacency matrix must be bool." ); + + using IndexType = typename Matrix::IndexType; + + if( A.getRows() != A.getColumns() ) { + throw std::logic_error( "The matrix is not square: " + std::to_string( A.getRows() ) + " rows, " + + std::to_string( A.getColumns() ) + " columns." ); + } + + const IndexType N = A.getRows(); + B.setDimensions( N, N ); + + // set row lengths + typename AdjacencyMatrix::CompressedRowLengthsVector rowLengths; + rowLengths.setSize( N ); + rowLengths.setValue( 0 ); + for( IndexType i = 0; i < A.getRows(); i++ ) { + const int maxLength = A.getRowLength( i ); + const auto row = A.getRow( i ); + IndexType length = 0; + for( int c_j = 0; c_j < maxLength; c_j++ ) { + const IndexType j = row.getElementColumn( c_j ); + if( j >= A.getColumns() ) + break; + length++; + if( ! has_symmetric_pattern && i != j ) + if( A.getElement( j, i ) == 0 ) + rowLengths[ j ]++; + } + if( ignore_diagonal ) + length--; + rowLengths[ i ] += length; + } + B.setCompressedRowLengths( rowLengths ); + + // set non-zeros + for( IndexType i = 0; i < A.getRows(); i++ ) { + const int maxLength = A.getRowLength( i ); + const auto row = A.getRow( i ); + for( int c_j = 0; c_j < maxLength; c_j++ ) { + const IndexType j = row.getElementColumn( c_j ); + if( j >= A.getColumns() ) + break; + if( ! ignore_diagonal || i != j ) + if( A.getElement( i, j ) != 0 ) { + B.setElement( i, j, true ); + if( ! has_symmetric_pattern ) + B.setElement( j, i, true ); + } + } + } +} + + +template< typename Matrix1, typename Matrix2, typename PermutationArray > +void +reorderSparseMatrix( const Matrix1& matrix1, Matrix2& matrix2, const PermutationArray& perm, const PermutationArray& iperm ) +{ + // TODO: implement on GPU + static_assert( std::is_same< typename Matrix1::DeviceType, Devices::Host >::value, "matrix reordering is implemented only for host" ); + static_assert( std::is_same< typename Matrix2::DeviceType, Devices::Host >::value, "matrix reordering is implemented only for host" ); + static_assert( std::is_same< typename PermutationArray::DeviceType, Devices::Host >::value, "matrix reordering is implemented only for host" ); + + using IndexType = typename Matrix1::IndexType; + + matrix2.setDimensions( matrix1.getRows(), matrix1.getColumns() ); + + // set row lengths + typename Matrix2::CompressedRowLengthsVector rowLengths; + rowLengths.setSize( matrix1.getRows() ); + for( IndexType i = 0; i < matrix1.getRows(); i++ ) { + const IndexType maxLength = matrix1.getRowLength( perm[ i ] ); + const auto row = matrix1.getRow( perm[ i ] ); + IndexType length = 0; + for( IndexType j = 0; j < maxLength; j++ ) + if( row.getElementColumn( j ) < matrix1.getColumns() ) + length++; + rowLengths[ i ] = length; + } + matrix2.setCompressedRowLengths( rowLengths ); + + // set row elements + for( IndexType i = 0; i < matrix2.getRows(); i++ ) { + const IndexType rowLength = rowLengths[ i ]; + + // extract sparse row + const auto row1 = matrix1.getRow( perm[ i ] ); + + // permute + typename Matrix2::IndexType columns[ rowLength ]; + typename Matrix2::RealType values[ rowLength ]; + for( IndexType j = 0; j < rowLength; j++ ) { + columns[ j ] = iperm[ row1.getElementColumn( j ) ]; + values[ j ] = row1.getElementValue( j ); + } + + // sort + IndexType indices[ rowLength ]; + for( IndexType j = 0; j < rowLength; j++ ) + indices[ j ] = j; + // nvcc does not allow lambdas to capture VLAs, even in host code (WTF!?) + // error: a variable captured by a lambda cannot have a type involving a variable-length array + IndexType* _columns = columns; + auto comparator = [=]( IndexType a, IndexType b ) { + return _columns[ a ] < _columns[ b ]; + }; + std::sort( indices, indices + rowLength, comparator ); + + typename Matrix2::IndexType sortedColumns[ rowLength ]; + typename Matrix2::RealType sortedValues[ rowLength ]; + for( IndexType j = 0; j < rowLength; j++ ) { + sortedColumns[ j ] = columns[ indices[ j ] ]; + sortedValues[ j ] = values[ indices[ j ] ]; + } + + matrix2.setRow( i, sortedColumns, sortedValues, rowLength ); + } +} + +template< typename Array1, typename Array2, typename PermutationArray > +void +reorderArray( const Array1& src, Array2& dest, const PermutationArray& perm ) +{ + static_assert( std::is_same< typename Array1::DeviceType, typename Array2::DeviceType >::value, + "Arrays must reside on the same device." ); + static_assert( std::is_same< typename Array1::DeviceType, typename PermutationArray::DeviceType >::value, + "Arrays must reside on the same device." ); + TNL_ASSERT_EQ( src.getSize(), perm.getSize(), + "Source array and permutation must have the same size." ); + TNL_ASSERT_EQ( dest.getSize(), perm.getSize(), + "Destination array and permutation must have the same size." ); + + using DeviceType = typename Array1::DeviceType; + using IndexType = typename Array1::IndexType; + + auto kernel = [] __cuda_callable__ + ( IndexType i, + const typename Array1::ValueType* src, + typename Array2::ValueType* dest, + const typename PermutationArray::ValueType* perm ) + { + dest[ i ] = src[ perm[ i ] ]; + }; + + ParallelFor< DeviceType >::exec( (IndexType) 0, src.getSize(), + kernel, + src.getData(), + dest.getData(), + perm.getData() ); +} + +} // namespace Matrices +} // namespace TNL diff --git a/src/TNL/Matrices/Sparse_impl.h b/src/TNL/Matrices/Sparse_impl.h index ba4558d3f..cd57637cb 100644 --- a/src/TNL/Matrices/Sparse_impl.h +++ b/src/TNL/Matrices/Sparse_impl.h @@ -11,7 +11,6 @@ #pragma once #include "Sparse.h" -#include namespace TNL { namespace Matrices { @@ -134,145 +133,5 @@ void Sparse< Real, Device, Index >::printStructure( std::ostream& str ) const TNL_ASSERT_TRUE( false, "Not implemented yet." ); } - -#ifdef HAVE_CUDA -template< typename Vector, typename Matrix > -__global__ void -SparseMatrixSetRowLengthsVectorKernel( Vector* rowLengths, - const Matrix* matrix, - typename Matrix::IndexType rows, - typename Matrix::IndexType cols ) -{ - using IndexType = typename Matrix::IndexType; - - IndexType rowIdx = blockIdx.x * blockDim.x + threadIdx.x; - const IndexType gridSize = blockDim.x * gridDim.x; - - while( rowIdx < rows ) { - const auto max_length = matrix->getRowLengthFast( rowIdx ); - const auto row = matrix->getRow( rowIdx ); - IndexType length = 0; - for( IndexType c_j = 0; c_j < max_length; c_j++ ) - if( row.getElementColumn( c_j ) < cols ) - length++; - else - break; - rowLengths[ rowIdx ] = length; - rowIdx += gridSize; - } -} - -template< typename Matrix1, typename Matrix2 > -__global__ void -SparseMatrixCopyKernel( Matrix1* A, - const Matrix2* B, - const typename Matrix2::IndexType* rowLengths, - typename Matrix2::IndexType rows ) -{ - using IndexType = typename Matrix2::IndexType; - - IndexType rowIdx = blockIdx.x * blockDim.x + threadIdx.x; - const IndexType gridSize = blockDim.x * gridDim.x; - - while( rowIdx < rows ) { - const auto length = rowLengths[ rowIdx ]; - const auto rowB = B->getRow( rowIdx ); - auto rowA = A->getRow( rowIdx ); - for( IndexType c = 0; c < length; c++ ) - rowA.setElement( c, rowB.getElementColumn( c ), rowB.getElementValue( c ) ); - rowIdx += gridSize; - } -} -#endif - -template< typename Matrix1, typename Matrix2 > -void -copySparseMatrix( Matrix1& A, const Matrix2& B ) -{ - static_assert( std::is_same< typename Matrix1::RealType, typename Matrix2::RealType >::value, - "The matrices must have the same RealType." ); - static_assert( std::is_same< typename Matrix1::DeviceType, typename Matrix2::DeviceType >::value, - "The matrices must be allocated on the same device." ); - static_assert( std::is_same< typename Matrix1::IndexType, typename Matrix2::IndexType >::value, - "The matrices must have the same IndexType." ); - - using RealType = typename Matrix1::RealType; - using DeviceType = typename Matrix1::DeviceType; - using IndexType = typename Matrix1::IndexType; - - const IndexType rows = B.getRows(); - const IndexType cols = B.getColumns(); - - A.setDimensions( rows, cols ); - - if( std::is_same< DeviceType, Devices::Host >::value ) { - // set row lengths - typename Matrix1::CompressedRowLengthsVector rowLengths; - rowLengths.setSize( rows ); -#ifdef HAVE_OPENMP -#pragma omp parallel for if( Devices::Host::isOMPEnabled() ) -#endif - for( IndexType i = 0; i < rows; i++ ) { - const auto max_length = B.getRowLength( i ); - const auto row = B.getRow( i ); - IndexType length = 0; - for( IndexType c_j = 0; c_j < max_length; c_j++ ) - if( row.getElementColumn( c_j ) < cols ) - length++; - else - break; - rowLengths[ i ] = length; - } - A.setCompressedRowLengths( rowLengths ); - -#ifdef HAVE_OPENMP -#pragma omp parallel for if( Devices::Host::isOMPEnabled() ) -#endif - for( IndexType i = 0; i < rows; i++ ) { - const auto length = rowLengths[ i ]; - const auto rowB = B.getRow( i ); - auto rowA = A.getRow( i ); - for( IndexType c = 0; c < length; c++ ) - rowA.setElement( c, rowB.getElementColumn( c ), rowB.getElementValue( c ) ); - } - } - - if( std::is_same< DeviceType, Devices::Cuda >::value ) { -#ifdef HAVE_CUDA - dim3 blockSize( 256 ); - dim3 gridSize; - const IndexType desGridSize = 32 * Devices::CudaDeviceInfo::getCudaMultiprocessors( Devices::CudaDeviceInfo::getActiveDevice() ); - gridSize.x = min( desGridSize, Devices::Cuda::getNumberOfBlocks( rows, blockSize.x ) ); - - typename Matrix1::CompressedRowLengthsVector rowLengths; - rowLengths.setSize( rows ); - - Pointers::DevicePointer< Matrix1 > Apointer( A ); - const Pointers::DevicePointer< const Matrix2 > Bpointer( B ); - - // set row lengths - Devices::Cuda::synchronizeDevice(); - SparseMatrixSetRowLengthsVectorKernel<<< gridSize, blockSize >>>( - rowLengths.getData(), - &Bpointer.template getData< TNL::Devices::Cuda >(), - rows, - cols ); - TNL_CHECK_CUDA_DEVICE; - Apointer->setCompressedRowLengths( rowLengths ); - - // copy rows - Devices::Cuda::synchronizeDevice(); - SparseMatrixCopyKernel<<< gridSize, blockSize >>>( - &Apointer.template modifyData< TNL::Devices::Cuda >(), - &Bpointer.template getData< TNL::Devices::Cuda >(), - rowLengths.getData(), - rows ); - TNL_CHECK_CUDA_DEVICE; -#else - throw Exceptions::CudaSupportMissing(); -#endif - } -} - } // namespace Matrices } // namespace TNL diff --git a/src/TNL/Solvers/Linear/BICGStab.h b/src/TNL/Solvers/Linear/BICGStab.h index 03b5f70b7..686d6f450 100644 --- a/src/TNL/Solvers/Linear/BICGStab.h +++ b/src/TNL/Solvers/Linear/BICGStab.h @@ -12,8 +12,6 @@ #include "LinearSolver.h" -#include - namespace TNL { namespace Solvers { namespace Linear { @@ -41,11 +39,11 @@ public: bool solve( ConstVectorViewType b, VectorViewType x ) override; protected: - void setSize( IndexType size ); + void setSize( const VectorViewType& x ); bool exact_residue = false; - Containers::Vector< RealType, DeviceType, IndexType > r, r_ast, p, s, Ap, As, M_tmp; + typename Traits< Matrix >::VectorType r, r_ast, p, s, Ap, As, M_tmp; }; } // namespace Linear diff --git a/src/TNL/Solvers/Linear/BICGStabL.h b/src/TNL/Solvers/Linear/BICGStabL.h index 77311c442..a35962d54 100644 --- a/src/TNL/Solvers/Linear/BICGStabL.h +++ b/src/TNL/Solvers/Linear/BICGStabL.h @@ -43,8 +43,6 @@ #include "LinearSolver.h" -#include - namespace TNL { namespace Solvers { namespace Linear { @@ -54,12 +52,18 @@ class BICGStabL : public LinearSolver< Matrix > { using Base = LinearSolver< Matrix >; + + // compatibility shortcut + using Traits = Linear::Traits< Matrix >; + public: using RealType = typename Base::RealType; using DeviceType = typename Base::DeviceType; using IndexType = typename Base::IndexType; + // distributed vectors/views using VectorViewType = typename Base::VectorViewType; using ConstVectorViewType = typename Base::ConstVectorViewType; + using VectorType = typename Traits::VectorType; String getType() const; @@ -75,7 +79,11 @@ protected: using DeviceVector = Containers::Vector< RealType, DeviceType, IndexType >; using HostVector = Containers::Vector< RealType, Devices::Host, IndexType >; - void setSize( IndexType size ); + void compute_residue( VectorViewType r, ConstVectorViewType x, ConstVectorViewType b ); + + void preconditioned_matvec( ConstVectorViewType src, VectorViewType dst ); + + void setSize( const VectorViewType& x ); int ell = 1; @@ -83,12 +91,13 @@ protected: // matrices (in column-major format) DeviceVector R, U; - // single vectors - DeviceVector r_ast, M_tmp, res_tmp; + // single vectors (distributed) + VectorType r_ast, M_tmp, res_tmp; // host-only storage HostVector T, sigma, g_0, g_1, g_2; - IndexType size, ldSize; + IndexType size = 0; + IndexType ldSize = 0; }; } // namespace Linear diff --git a/src/TNL/Solvers/Linear/BICGStabL_impl.h b/src/TNL/Solvers/Linear/BICGStabL_impl.h index 6606bddd5..8338a3f96 100644 --- a/src/TNL/Solvers/Linear/BICGStabL_impl.h +++ b/src/TNL/Solvers/Linear/BICGStabL_impl.h @@ -22,7 +22,8 @@ namespace Linear { template< typename Matrix > String -BICGStabL< Matrix >::getType() const +BICGStabL< Matrix >:: +getType() const { return String( "BICGStabL< " ) + this->matrix -> getType() + ", " + @@ -52,39 +53,30 @@ setup( const Config::ParameterContainer& parameters, template< typename Matrix > bool -BICGStabL< Matrix >::solve( ConstVectorViewType b, VectorViewType x ) +BICGStabL< Matrix >:: +solve( ConstVectorViewType b, VectorViewType x ) { - this->setSize( this->matrix->getRows() ); + this->setSize( x ); RealType alpha, beta, gamma, rho_0, rho_1, omega, b_norm; - DeviceVector r_0, r_j, r_i, u_0, Au, u; + // initial binding to M_tmp sets the correct local range, global size and + // communication group for distributed views + VectorViewType r_0( M_tmp ), r_j( M_tmp ), r_i( M_tmp ), u_0( M_tmp ), Au( M_tmp ), u( M_tmp ); r_0.bind( R.getData(), size ); u_0.bind( U.getData(), size ); - auto matvec = [this]( const DeviceVector& src, DeviceVector& dst ) - { - if( this->preconditioner ) { - this->matrix->vectorProduct( src, M_tmp ); - this->preconditioner->solve( M_tmp, dst ); - } - else { - this->matrix->vectorProduct( src, dst ); - } - }; - + // initialize the norm of the preconditioned right-hand-side if( this->preconditioner ) { this->preconditioner->solve( b, M_tmp ); - b_norm = M_tmp.lpNorm( ( RealType ) 2.0 ); - - this->matrix->vectorProduct( x, M_tmp ); - M_tmp.addVector( b, 1.0, -1.0 ); - this->preconditioner->solve( M_tmp, r_0 ); + b_norm = M_tmp.lpNorm( 2.0 ); } - else { + else b_norm = b.lpNorm( 2.0 ); - this->matrix->vectorProduct( x, r_0 ); - r_0.addVector( b, 1.0, -1.0 ); - } + if( b_norm == 0.0 ) + b_norm = 1.0; + + // r_0 = M.solve(b - A * x); + compute_residue( r_0, x, b ); sigma[ 0 ] = r_0.lpNorm( 2.0 ); if( std::isnan( sigma[ 0 ] ) ) @@ -97,9 +89,6 @@ BICGStabL< Matrix >::solve( ConstVectorViewType b, VectorViewType x ) omega = 1.0; u_0.setValue( 0.0 ); - if( b_norm == 0.0 ) - b_norm = 1.0; - this->resetIterations(); this->setResidue( sigma[ 0 ] / b_norm ); @@ -132,7 +121,7 @@ BICGStabL< Matrix >::solve( ConstVectorViewType b, VectorViewType x ) */ u.bind( &U.getData()[ j * ldSize ], size ); Au.bind( &U.getData()[ (j + 1) * ldSize ], size ); - matvec( u, Au ); + preconditioned_matvec( u, Au ); gamma = r_ast.scalarProduct( Au ); alpha = rho_0 / gamma; @@ -151,7 +140,7 @@ BICGStabL< Matrix >::solve( ConstVectorViewType b, VectorViewType x ) */ r_j.bind( &R.getData()[ j * ldSize ], size ); r_i.bind( &R.getData()[ (j + 1) * ldSize ], size ); - matvec( r_j, r_i ); + preconditioned_matvec( r_j, r_i ); /**** * x_0 := x_0 + alpha * u_0 @@ -227,29 +216,21 @@ BICGStabL< Matrix >::solve( ConstVectorViewType b, VectorViewType x ) g_2[ 0 ] = g_0[ 1 ]; MatrixOperations< DeviceType >::gemv( size, ell, 1.0, R.getData(), ldSize, g_2.getData(), - 1.0, x.getData() ); + 1.0, Traits::getLocalVectorView( x ).getData() ); // r_0 := r_0 - R_[1:ell] * g_1_[1:ell] MatrixOperations< DeviceType >::gemv( size, ell, -1.0, R.getData() + ldSize, ldSize, &g_1[ 1 ], - 1.0, r_0.getData() ); + 1.0, Traits::getLocalVectorView( r_0 ).getData() ); // u_0 := u_0 - U_[1:ell] * g_0_[1:ell] MatrixOperations< DeviceType >::gemv( size, ell, -1.0, U.getData() + ldSize, ldSize, &g_0[ 1 ], - 1.0, u_0.getData() ); + 1.0, Traits::getLocalVectorView( u_0 ).getData() ); if( exact_residue ) { /**** * Compute the exact preconditioned residue into the 's' vector. */ - if( this->preconditioner ) { - this->matrix->vectorProduct( x, M_tmp ); - M_tmp.addVector( b, 1.0, -1.0 ); - this->preconditioner->solve( M_tmp, res_tmp ); - } - else { - this->matrix->vectorProduct( x, res_tmp ); - res_tmp.addVector( b, 1.0, -1.0 ); - } + compute_residue( res_tmp, x, b ); sigma[ 0 ] = res_tmp.lpNorm( 2.0 ); this->setResidue( sigma[ 0 ] / b_norm ); } @@ -268,15 +249,49 @@ BICGStabL< Matrix >::solve( ConstVectorViewType b, VectorViewType x ) template< typename Matrix > void -BICGStabL< Matrix >::setSize( IndexType size ) +BICGStabL< Matrix >:: +compute_residue( VectorViewType r, ConstVectorViewType x, ConstVectorViewType b ) +{ + /**** + * r = M.solve(b - A * x); + */ + if( this->preconditioner ) { + this->matrix->vectorProduct( x, M_tmp ); + M_tmp.addVector( b, 1.0, -1.0 ); + this->preconditioner->solve( M_tmp, r ); + } + else { + this->matrix->vectorProduct( x, r ); + r.addVector( b, 1.0, -1.0 ); + } +} + +template< typename Matrix > +void +BICGStabL< Matrix >:: +preconditioned_matvec( ConstVectorViewType src, VectorViewType dst ) +{ + if( this->preconditioner ) { + this->matrix->vectorProduct( src, M_tmp ); + this->preconditioner->solve( M_tmp, dst ); + } + else { + this->matrix->vectorProduct( src, dst ); + } +} + +template< typename Matrix > +void +BICGStabL< Matrix >:: +setSize( const VectorViewType& x ) { - this->size = ldSize = size; + this->size = ldSize = Traits::getLocalVectorView( x ).getSize(); R.setSize( (ell + 1) * ldSize ); U.setSize( (ell + 1) * ldSize ); - r_ast.setSize( size ); - M_tmp.setSize( size ); + r_ast.setLike( x ); + M_tmp.setLike( x ); if( exact_residue ) - res_tmp.setSize( size ); + res_tmp.setLike( x ); T.setSize( ell * ell ); sigma.setSize( ell + 1 ); g_0.setSize( ell + 1 ); diff --git a/src/TNL/Solvers/Linear/BICGStab_impl.h b/src/TNL/Solvers/Linear/BICGStab_impl.h index 86702b310..e0313e004 100644 --- a/src/TNL/Solvers/Linear/BICGStab_impl.h +++ b/src/TNL/Solvers/Linear/BICGStab_impl.h @@ -48,7 +48,7 @@ setup( const Config::ParameterContainer& parameters, template< typename Matrix > bool BICGStab< Matrix >::solve( ConstVectorViewType b, VectorViewType x ) { - this->setSize( this->matrix->getRows() ); + this->setSize( x ); RealType alpha, beta, omega, aux, rho, rho_old, b_norm; @@ -161,15 +161,15 @@ bool BICGStab< Matrix >::solve( ConstVectorViewType b, VectorViewType x ) } template< typename Matrix > -void BICGStab< Matrix > :: setSize( IndexType size ) +void BICGStab< Matrix > :: setSize( const VectorViewType& x ) { - r.setSize( size ); - r_ast.setSize( size ); - p.setSize( size ); - s.setSize( size ); - Ap.setSize( size ); - As.setSize( size ); - M_tmp.setSize( size ); + r.setLike( x ); + r_ast.setLike( x ); + p.setLike( x ); + s.setLike( x ); + Ap.setLike( x ); + As.setLike( x ); + M_tmp.setLike( x ); } } // namespace Linear diff --git a/src/TNL/Solvers/Linear/CMakeLists.txt b/src/TNL/Solvers/Linear/CMakeLists.txt index f44f0a095..2e33af0b8 100644 --- a/src/TNL/Solvers/Linear/CMakeLists.txt +++ b/src/TNL/Solvers/Linear/CMakeLists.txt @@ -6,8 +6,6 @@ SET( headers BICGStab.h BICGStabL_impl.h CG.h CG_impl.h - CWYGMRES.h - CWYGMRES_impl.h GMRES.h GMRES_impl.h Jacobi.h diff --git a/src/TNL/Solvers/Linear/CWYGMRES.h b/src/TNL/Solvers/Linear/CWYGMRES.h deleted file mode 100644 index 1cccc132d..000000000 --- a/src/TNL/Solvers/Linear/CWYGMRES.h +++ /dev/null @@ -1,115 +0,0 @@ -/*************************************************************************** - CWYGMRES.h - description - ------------------- - begin : May 13, 2016 - copyright : (C) 2016 by Tomas Oberhuber et al. - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -// Implemented by: Jakub Klinkovsky - -#pragma once - -#include "LinearSolver.h" - -#include - -namespace TNL { -namespace Solvers { -namespace Linear { - -template< typename Matrix > -class CWYGMRES -: public LinearSolver< Matrix > -{ - using Base = LinearSolver< Matrix >; -public: - using RealType = typename Base::RealType; - using DeviceType = typename Base::DeviceType; - using IndexType = typename Base::IndexType; - using VectorViewType = typename Base::VectorViewType; - using ConstVectorViewType = typename Base::ConstVectorViewType; - - String getType() const; - - static void configSetup( Config::ConfigDescription& config, - const String& prefix = "" ); - - bool setup( const Config::ParameterContainer& parameters, - const String& prefix = "" ) override; - - void setRestarting( IndexType rest ); - - bool solve( ConstVectorViewType b, VectorViewType x ) override; - -protected: - using DeviceVector = Containers::Vector< RealType, DeviceType, IndexType >; - using HostVector = Containers::Vector< RealType, Devices::Host, IndexType >; - - void hauseholder_generate( DeviceVector& Y, - HostVector& T, - const int& i, - DeviceVector& w ); - - void hauseholder_apply_trunc( HostVector& out, - DeviceVector& Y, - HostVector& T, - const int& i, - DeviceVector& w ); - - void hauseholder_cwy( DeviceVector& w, - DeviceVector& Y, - HostVector& T, - const int& i ); - - void hauseholder_cwy_transposed( DeviceVector& w, - DeviceVector& Y, - HostVector& T, - const int& i, - DeviceVector& z ); - - template< typename Vector > - void update( IndexType k, - IndexType m, - const HostVector& H, - const HostVector& s, - DeviceVector& v, - Vector& x ); - - void generatePlaneRotation( RealType& dx, - RealType& dy, - RealType& cs, - RealType& sn ); - - void applyPlaneRotation( RealType& dx, - RealType& dy, - RealType& cs, - RealType& sn ); - - - void setSize( IndexType _size, IndexType m ); - - // single vectors - DeviceVector r, z, w, _M_tmp; - // matrices (in column-major format) - DeviceVector V, Y; - // duplicate of the upper (m+1)x(m+1) submatrix of Y (it is lower triangular) for fast access - HostVector YL, T; - // host-only storage for Givens rotations and the least squares problem - HostVector cs, sn, H, s; - - IndexType size = 0; - IndexType ldSize = 0; - IndexType restarting_min = 10; - IndexType restarting_max = 10; - IndexType restarting_step_min = 3; - IndexType restarting_step_max = 3; -}; - -} // namespace Linear -} // namespace Solvers -} // namespace TNL - -#include "CWYGMRES_impl.h" diff --git a/src/TNL/Solvers/Linear/CWYGMRES_impl.h b/src/TNL/Solvers/Linear/CWYGMRES_impl.h deleted file mode 100644 index 4989f5020..000000000 --- a/src/TNL/Solvers/Linear/CWYGMRES_impl.h +++ /dev/null @@ -1,633 +0,0 @@ -/*************************************************************************** - CWYGMRES.h - description - ------------------- - begin : May 13, 2016 - copyright : (C) 2016 by Tomas Oberhuber et al. - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -// Implemented by: Jakub Klinkovsky - -#pragma once - -#include -#include - -#include -#include -#include - -#include "CWYGMRES.h" - -namespace TNL { -namespace Solvers { -namespace Linear { - -template< typename Matrix > -String -CWYGMRES< Matrix >:: -getType() const -{ - return String( "CWYGMRES< " ) + - this->matrix -> getType() + ", " + - this->preconditioner -> getType() + " >"; -} - -template< typename Matrix > -void -CWYGMRES< Matrix >:: -configSetup( Config::ConfigDescription& config, - const String& prefix ) -{ - config.addEntry< int >( prefix + "gmres-restarting-min", "Minimal number of iterations after which the GMRES restarts.", 10 ); - config.addEntry< int >( prefix + "gmres-restarting-max", "Maximal number of iterations after which the GMRES restarts.", 10 ); - config.addEntry< int >( prefix + "gmres-restarting-step-min", "Minimal adjusting step for the adaptivity of the GMRES restarting parameter.", 3 ); - config.addEntry< int >( prefix + "gmres-restarting-step-max", "Maximal adjusting step for the adaptivity of the GMRES restarting parameter.", 3 ); -} - -template< typename Matrix > -bool -CWYGMRES< Matrix >:: -setup( const Config::ParameterContainer& parameters, - const String& prefix ) -{ - restarting_min = parameters.getParameter< int >( "gmres-restarting-min" ); - this->setRestarting( parameters.getParameter< int >( "gmres-restarting-max" ) ); - restarting_step_min = parameters.getParameter< int >( "gmres-restarting-step-min" ); - restarting_step_max = parameters.getParameter< int >( "gmres-restarting-step-max" ); - return LinearSolver< Matrix >::setup( parameters, prefix ); -} - -template< typename Matrix > -void -CWYGMRES< Matrix >:: -setRestarting( IndexType rest ) -{ - if( size != 0 ) - setSize( size, rest ); - restarting_max = rest; -} - -template< typename Matrix > -bool -CWYGMRES< Matrix >:: -solve( ConstVectorViewType b, VectorViewType x ) -{ - TNL_ASSERT_TRUE( this->matrix, "No matrix was set in CWYGMRES. Call setMatrix() before solve()." ); - if( restarting_min <= 0 || restarting_max <= 0 || restarting_min > restarting_max ) - { - std::cerr << "Wrong value for the GMRES restarting parameters: r_min = " << restarting_min - << ", r_max = " << restarting_max << std::endl; - return false; - } - if( restarting_step_min < 0 || restarting_step_max < 0 || restarting_step_min > restarting_step_max ) - { - std::cerr << "Wrong value for the GMRES restarting adjustment parameters: d_min = " << restarting_step_min - << ", d_max = " << restarting_step_max << std::endl; - return false; - } - setSize( this->matrix->getRows(), restarting_max ); - - RealType normb( 0.0 ), beta( 0.0 ); - /**** - * 1. Solve r from M r = b - A x_0 - */ - if( this->preconditioner ) - { - this->preconditioner->solve( b, _M_tmp ); - normb = _M_tmp.lpNorm( ( RealType ) 2.0 ); - - this->matrix->vectorProduct( x, _M_tmp ); - _M_tmp.addVector( b, ( RealType ) 1.0, -1.0 ); - - this->preconditioner->solve( _M_tmp, r ); - } - else - { - this->matrix->vectorProduct( x, r ); - normb = b.lpNorm( ( RealType ) 2.0 ); - r.addVector( b, ( RealType ) 1.0, -1.0 ); - } - beta = r.lpNorm( ( RealType ) 2.0 ); - - //cout << "norm b = " << normb <nextIteration(); i++ ) - { -// std::cout << "==== i = " << i << " ====" <preconditioner ) - { - this->matrix->vectorProduct( vi, _M_tmp ); - this->preconditioner->solve( _M_tmp, w ); - } - else - this->matrix->vectorProduct( vi, w ); - - /**** - * Apply all previous Hauseholder transformations, using the compact WY representation: - * z = (I - Y_i * T_i^T * Y_i^T) * w - */ - hauseholder_cwy_transposed( z, Y, T, i, w ); - } - -// std::cout << "vi.norm = " << vi.lpNorm( 2.0 ) < - namespace TNL { namespace Solvers { namespace Linear { @@ -23,12 +23,19 @@ class GMRES : public LinearSolver< Matrix > { using Base = LinearSolver< Matrix >; + + // compatibility shortcuts + using Traits = Linear::Traits< Matrix >; + using CommunicatorType = typename Traits::CommunicatorType; + public: using RealType = typename Base::RealType; using DeviceType = typename Base::DeviceType; using IndexType = typename Base::IndexType; + // distributed vectors/views using VectorViewType = typename Base::VectorViewType; using ConstVectorViewType = typename Base::ConstVectorViewType; + using VectorType = typename Traits::VectorType; String getType() const; @@ -38,18 +45,56 @@ public: bool setup( const Config::ParameterContainer& parameters, const String& prefix = "" ) override; - void setRestarting( IndexType rest ); - bool solve( ConstVectorViewType b, VectorViewType x ) override; protected: - template< typename VectorT > - void update( IndexType k, - IndexType m, - const Containers::Vector< RealType, Devices::Host, IndexType >& H, - const Containers::Vector< RealType, Devices::Host, IndexType >& s, - Containers::Vector< RealType, DeviceType, IndexType >& v, - VectorT& x ); + // local vectors/views + using ConstDeviceView = typename Traits::ConstLocalVectorViewType; + using DeviceView = typename Traits::LocalVectorViewType; + using HostView = typename DeviceView::HostType; + using DeviceVector = typename Traits::LocalVectorType; + using HostVector = typename DeviceVector::HostType; + + enum class Variant { MGS, MGSR, CWY }; + + int orthogonalize_MGS( const int m, const RealType normb, const RealType beta ); + + int orthogonalize_CWY( const int m, const RealType normb, const RealType beta ); + + void compute_residue( VectorViewType r, ConstVectorViewType x, ConstVectorViewType b ); + + void preconditioned_matvec( VectorViewType w, ConstVectorViewType v ); + +// nvcc allows __cuda_callable__ lambdas only in public methods +#ifdef __NVCC__ +public: +#endif + void hauseholder_generate( const int i, + VectorViewType y_i, + ConstVectorViewType z ); +#ifdef __NVCC__ +protected: +#endif + + void hauseholder_apply_trunc( HostView out, + const int i, + VectorViewType y_i, + ConstVectorViewType z ); + + void hauseholder_cwy( VectorViewType v, + const int i ); + + void hauseholder_cwy_transposed( VectorViewType z, + const int i, + ConstVectorViewType w ); + + template< typename Vector > + void update( const int k, + const int m, + const HostVector& H, + const HostVector& s, + DeviceVector& V, + Vector& x ); void generatePlaneRotation( RealType& dx, RealType& dy, @@ -61,17 +106,43 @@ protected: RealType& cs, RealType& sn ); + void apply_givens_rotations( const int i, const int m ); + + void setSize( const VectorViewType& x ); + + // Specialized methods to distinguish between normal and distributed matrices + // in the implementation. + template< typename M > + static IndexType getLocalOffset( const M& m ) + { + return 0; + } + + template< typename M > + static IndexType getLocalOffset( const DistributedContainers::DistributedMatrix< M >& m ) + { + return m.getLocalRowRange().getBegin(); + } - void setSize( IndexType _size, IndexType m ); + // selected GMRES variant + Variant variant = Variant::CWY; - Containers::Vector< RealType, DeviceType, IndexType > _r, w, _v, _M_tmp; - Containers::Vector< RealType, Devices::Host, IndexType > _s, _cs, _sn, _H; + // single vectors (distributed) + VectorType r, w, z, _M_tmp; + // matrices (in column-major format) (local) + DeviceVector V, Y; + // (CWY only) duplicate of the upper (m+1)x(m+1) submatrix of Y (it is lower triangular) for fast access + HostVector YL, T; + // host-only storage for Givens rotations and the least squares problem + HostVector cs, sn, H, s; IndexType size = 0; - IndexType restarting_min = 10; - IndexType restarting_max = 10; - IndexType restarting_step_min = 3; - IndexType restarting_step_max = 3; + IndexType ldSize = 0; + IndexType localOffset = 0; + int restarting_min = 10; + int restarting_max = 10; + int restarting_step_min = 3; + int restarting_step_max = 3; }; } // namespace Linear diff --git a/src/TNL/Solvers/Linear/GMRES_impl.h b/src/TNL/Solvers/Linear/GMRES_impl.h index 220cecf23..eb2dd89d3 100644 --- a/src/TNL/Solvers/Linear/GMRES_impl.h +++ b/src/TNL/Solvers/Linear/GMRES_impl.h @@ -1,17 +1,24 @@ /*************************************************************************** GMRES_impl.h - description ------------------- - begin : Nov 25, 2012 - copyright : (C) 2012 by Tomas Oberhuber + begin : May 13, 2016 + copyright : (C) 2016 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ /* See Copyright Notice in tnl/Copyright */ +// Implemented by: Jakub Klinkovsky + #pragma once +#include #include +#include +#include +#include + #include "GMRES.h" namespace TNL { @@ -34,6 +41,10 @@ GMRES< Matrix >:: configSetup( Config::ConfigDescription& config, const String& prefix ) { + config.addEntry< String >( prefix + "gmres-variant", "Minimal number of iterations after which the GMRES restarts.", "CWY" ); + config.addEntryEnum( "MGS" ); + config.addEntryEnum( "MGSR" ); + config.addEntryEnum( "CWY" ); config.addEntry< int >( prefix + "gmres-restarting-min", "Minimal number of iterations after which the GMRES restarts.", 10 ); config.addEntry< int >( prefix + "gmres-restarting-max", "Maximal number of iterations after which the GMRES restarts.", 10 ); config.addEntry< int >( prefix + "gmres-restarting-step-min", "Minimal adjusting step for the adaptivity of the GMRES restarting parameter.", 3 ); @@ -46,21 +57,22 @@ GMRES< Matrix >:: setup( const Config::ParameterContainer& parameters, const String& prefix ) { + const String var = parameters.getParameter< String >( "gmres-variant" ); + if( var == "MGS" ) + variant = Variant::MGS; + else if( var == "MGSR" ) + variant = Variant::MGSR; + else if( var == "CWY" ) + variant = Variant::CWY; + else + return false; + restarting_min = parameters.getParameter< int >( "gmres-restarting-min" ); - this->setRestarting( parameters.getParameter< int >( "gmres-restarting-max" ) ); + restarting_max = parameters.getParameter< int >( "gmres-restarting-max" ); restarting_step_min = parameters.getParameter< int >( "gmres-restarting-step-min" ); restarting_step_max = parameters.getParameter< int >( "gmres-restarting-step-max" ); - return LinearSolver< Matrix >::setup( parameters, prefix ); -} -template< typename Matrix > -void -GMRES< Matrix >:: -setRestarting( IndexType rest ) -{ - if( size != 0 ) - setSize( size, rest ); - restarting_max = rest; + return LinearSolver< Matrix >::setup( parameters, prefix ); } template< typename Matrix > @@ -69,58 +81,34 @@ GMRES< Matrix >:: solve( ConstVectorViewType b, VectorViewType x ) { TNL_ASSERT_TRUE( this->matrix, "No matrix was set in GMRES. Call setMatrix() before solve()." ); - if( restarting_min <= 0 || restarting_max <= 0 || restarting_min > restarting_max ) - { + if( restarting_min <= 0 || restarting_max <= 0 || restarting_min > restarting_max ) { std::cerr << "Wrong value for the GMRES restarting parameters: r_min = " << restarting_min << ", r_max = " << restarting_max << std::endl; return false; } - if( restarting_step_min < 0 || restarting_step_max < 0 || restarting_step_min > restarting_step_max ) - { + if( restarting_step_min < 0 || restarting_step_max < 0 || restarting_step_min > restarting_step_max ) { std::cerr << "Wrong value for the GMRES restarting adjustment parameters: d_min = " << restarting_step_min << ", d_max = " << restarting_step_max << std::endl; return false; } - setSize( this->matrix->getRows(), restarting_max ); - - IndexType _size = size; - - //RealType *w = _w.getData(); - RealType *s = _s.getData(); - RealType *cs = _cs.getData(); - RealType *sn = _sn.getData(); - RealType *v = _v.getData(); - RealType *H = _H.getData(); - RealType *M_tmp = _M_tmp.getData(); - - RealType normb( 0.0 ), beta( 0.0 ); - /**** - * 1. Solve r from M r = b - A x_0 - */ - if( this->preconditioner ) - { - this->preconditioner->solve( b, _M_tmp ); - normb = _M_tmp.lpNorm( ( RealType ) 2.0 ); - - this->matrix->vectorProduct( x, _M_tmp ); - _M_tmp.addVector( b, ( RealType ) 1.0, -1.0 ); + setSize( x ); - this->preconditioner->solve( _M_tmp, _r ); + // initialize the norm of the preconditioned right-hand-side + RealType normb; + if( this->preconditioner ) { + this->preconditioner->solve( b, _M_tmp ); + normb = _M_tmp.lpNorm( 2.0 ); } else - { - this->matrix->vectorProduct( x, _r ); - normb = b.lpNorm( ( RealType ) 2.0 ); - _r.addVector( b, ( RealType ) 1.0, -1.0 ); - } - beta = _r.lpNorm( ( RealType ) 2.0 ); - - //cout << "norm b = " << normb << std::endl; - //cout << " beta = " << beta << std::endl; - + normb = b.lpNorm( 2.0 ); + if( normb == 0.0 ) + normb = 1.0; - if( normb == 0.0 ) normb = 1.0; + // r = M.solve(b - A * x); + compute_residue( r, x, b ); + RealType beta = r.lpNorm( 2.0 ); + // initialize stopping criterion this->resetIterations(); this->setResidue( beta / normb ); @@ -131,9 +119,7 @@ solve( ConstVectorViewType b, VectorViewType x ) int restart_cycles = 0; // counter of restart cycles int m = restarting_max; // current restarting parameter - Containers::Vector< RealType, DeviceType, IndexType > vi, vk; - while( this->checkNextIteration() ) - { + while( this->checkNextIteration() ) { // adaptivity of the restarting parameter // reference: A.H. Baker, E.R. Jessup, Tz.V. Kolev - A simple strategy for varying the restart parameter in GMRES(m) // http://www.sciencedirect.com/science/article/pii/S0377042709000132 @@ -153,185 +139,452 @@ solve( ConstVectorViewType b, VectorViewType x ) // set restarting_max when we hit restarting_min (see Baker et al. (2009)) m = restarting_max; } -// std::cerr << "restarting: cycle = " << restart_cycles << ", beta_ratio = " << beta_ratio << ", m = " << m << " " << std::endl; } - for( IndexType i = 0; i < m + 1; i ++ ) - H[ i ] = s[ i ] = cs[ i ] = sn[ i ] = 0.0; + // orthogonalization + int o_steps = 0; + switch( variant ) { + case Variant::MGS: + case Variant::MGSR: + o_steps = orthogonalize_MGS( m, normb, beta ); + break; + case Variant::CWY: + o_steps = orthogonalize_CWY( m, normb, beta ); + break; + } + + if( o_steps < m ) { + // exact solution has been reached early + update( o_steps, m, H, s, V, x ); + this->refreshSolverMonitor( true ); + return this->checkConvergence(); + } + + // update the solution approximation + update( m - 1, m, H, s, V, x ); + + // compute the new residual vector + compute_residue( r, x, b ); + const RealType beta_old = beta; + beta = r.lpNorm( 2.0 ); + this->setResidue( beta / normb ); + + // update parameters for the adaptivity of the restarting parameter + ++restart_cycles; + beta_ratio = beta / beta_old; + } + + this->refreshSolverMonitor( true ); + return this->checkConvergence(); +} +template< typename Matrix > +int +GMRES< Matrix >:: +orthogonalize_MGS( const int m, const RealType normb, const RealType beta ) +{ + // initial binding to _M_tmp sets the correct local range, global size and + // communication group for distributed views + VectorViewType v_i( _M_tmp ), v_k( _M_tmp ); + + /*** + * v_0 = r / | r | = 1.0 / beta * r + */ + v_i.bind( V.getData(), size ); + v_i.addVector( r, 1.0 / beta, 0.0 ); + + H.setValue( 0.0 ); + s.setValue( 0.0 ); + s[ 0 ] = beta; + + /**** + * Starting m-loop + */ + for( int i = 0; i < m && this->nextIteration(); i++ ) { + v_i.bind( &V.getData()[ i * ldSize ], size ); /**** - * v = 0 + * Solve w from M w = A v_i + */ + preconditioned_matvec( w, v_i ); + + for( int k = 0; k <= i; k++ ) + H[ k + i * ( m + 1 ) ] = 0.0; + const int reorthogonalize = (variant == Variant::MGSR) ? 2 : 1; + for( int l = 0; l < reorthogonalize; l++ ) + for( int k = 0; k <= i; k++ ) { + v_k.bind( &V.getData()[ k * ldSize ], size ); + /*** + * H_{k,i} = ( w, v_k ) + */ + RealType H_k_i = w.scalarProduct( v_k ); + H[ k + i * ( m + 1 ) ] += H_k_i; + + /**** + * w = w - H_{k,i} v_k + */ + w.addVector( v_k, -H_k_i ); + } + /*** + * H_{i+1,i} = |w| */ - _v.setValue( ( RealType ) 0.0 ); + RealType normw = w.lpNorm( ( RealType ) 2.0 ); + H[ i + 1 + i * ( m + 1 ) ] = normw; /*** - * v_0 = r / | r | = 1.0 / beta * r + * v_{i+1} = w / |w| */ - vi.bind( _v.getData(), size ); - vi.addVector( _r, ( RealType ) 1.0 / beta ); + v_i.bind( &V.getData()[ ( i + 1 ) * ldSize ], size ); + v_i.addVector( w, 1.0 / normw, 0.0 ); + + /**** + * Applying the Givens rotations G_0, ..., G_i + */ + apply_givens_rotations( i, m ); + + this->setResidue( std::fabs( s[ i + 1 ] ) / normb ); + if( ! this->checkNextIteration() ) + return i; + else + this->refreshSolverMonitor(); + } + + return m; +} + +template< typename Matrix > +int +GMRES< Matrix >:: +orthogonalize_CWY( const int m, const RealType normb, const RealType beta ) +{ + // initial binding to _M_tmp sets the correct local range, global size and + // communication group for distributed views + VectorViewType v_i( _M_tmp ), y_i( _M_tmp ); - _s.setValue( ( RealType ) 0.0 ); - _s[ 0 ] = beta; + /*** + * z = r / | r | = 1.0 / beta * r + */ + // TODO: investigate normalization by beta and normb +// z.addVector( r, 1.0 / beta, 0.0 ); +// z.addVector( r, 1.0 / normb, 0.0 ); + z = r; + H.setValue( 0.0 ); + s.setValue( 0.0 ); + T.setValue( 0.0 ); + // NOTE: this is unstable, s[0] is set later in hauseholder_apply_trunc +// s[ 0 ] = beta; + /**** + * Starting m-loop + */ + for( int i = 0; i <= m && this->nextIteration(); i++ ) { /**** - * Starting m-loop + * Generate new Hauseholder transformation from vector z. */ - for( IndexType i = 0; i < m && this->nextIteration(); i++ ) - { - vi.bind( &( _v.getData()[ i * size ] ), size ); + y_i.bind( &Y.getData()[ i * ldSize ], size ); + hauseholder_generate( i, y_i, z ); + + if( i == 0 ) { /**** - * Solve w from M w = A v_i + * s = e_1^T * P_i * z */ - if( this->preconditioner ) - { - this->matrix->vectorProduct( vi, _M_tmp ); - this->preconditioner->solve( _M_tmp, w ); - } - else - this->matrix->vectorProduct( vi, w ); - - //cout << " i = " << i << " vi = " << vi << std::endl; - - for( IndexType k = 0; k <= i; k++ ) - H[ k + i * ( m + 1 ) ] = 0.0; - for( IndexType l = 0; l < 2; l++ ) - for( IndexType k = 0; k <= i; k++ ) - { - vk.bind( &( _v.getData()[ k * _size ] ), _size ); - /*** - * H_{k,i} = ( w, v_k ) - */ - RealType H_k_i = w.scalarProduct( vk ); - H[ k + i * ( m + 1 ) ] += H_k_i; - - /**** - * w = w - H_{k,i} v_k - */ - w.addVector( vk, -H_k_i ); - - //cout << "H_ki = " << H_k_i << std::endl; - //cout << "w = " << w << std::endl; - } + hauseholder_apply_trunc( s, i, y_i, z ); + } + else { /*** - * H_{i+1,i} = |w| + * H_{i-1} = P_i * z */ - RealType normw = w.lpNorm( ( RealType ) 2.0 ); - H[ i + 1 + i * ( m + 1 ) ] = normw; + HostView h( &H.getData()[ (i - 1) * (m + 1) ], m + 1 ); + hauseholder_apply_trunc( h, i, y_i, z ); + } - //cout << "normw = " << normw << std::endl; - - /*** - * v_{i+1} = w / |w| - */ - vi.bind( &( _v.getData()[ ( i + 1 ) * size ] ), size ); - vi.addVector( w, ( RealType ) 1.0 / normw ); - - //cout << "vi = " << vi << std::endl; - + /*** + * Generate new basis vector v_i, using the compact WY representation: + * v_i = (I - Y_i * T_i Y_i^T) * e_i + */ + v_i.bind( &V.getData()[ i * ldSize ], size ); + hauseholder_cwy( v_i, i ); + + if( i < m ) { /**** - * Applying the Givens rotations + * Solve w from M w = A v_i */ - for( IndexType k = 0; k < i; k++ ) - applyPlaneRotation( H[ k + i * ( m + 1 )], - H[ k + 1 + i * ( m + 1 ) ], - cs[ k ], - sn[ k ] ); - - generatePlaneRotation( H[ i + i * ( m + 1 ) ], - H[ i + 1 + i * ( m + 1 ) ], - cs[ i ], - sn[ i ]); - applyPlaneRotation( H[ i + i * ( m + 1 ) ], - H[ i + 1 + i * ( m + 1 ) ], - cs[ i ], - sn[ i ]); - applyPlaneRotation( s[ i ], - s[ i + 1 ], - cs[ i ], - sn[ i ] ); + preconditioned_matvec( w, v_i ); - this->setResidue( std::fabs( s[ i + 1 ] ) / normb ); - if( ! this->checkNextIteration() ) { - update( i, m, _H, _s, _v, x ); - this->refreshSolverMonitor( true ); - return this->checkConvergence(); - } - else - { - this->refreshSolverMonitor(); - } + /**** + * Apply all previous Hauseholder transformations, using the compact WY representation: + * z = (I - Y_i * T_i^T * Y_i^T) * w + */ + hauseholder_cwy_transposed( z, i, w ); } - //cout << "x = " << x << std::endl; - update( m - 1, m, _H, _s, _v, x ); - //cout << "x = " << x << std::endl; /**** - * r = M.solve(b - A * x); + * Applying the Givens rotations G_0, ..., G_{i-1} */ - const RealType beta_old = beta; - beta = 0.0; - if( this->preconditioner ) - { - this->matrix->vectorProduct( x, _M_tmp ); - _M_tmp.addVector( b, ( RealType ) 1.0, -1.0 ); - this->preconditioner->solve( _M_tmp, _r ); - beta = _r.lpNorm( ( RealType ) 2.0 ); - } + if( i > 0 ) + apply_givens_rotations( i - 1, m ); + + this->setResidue( std::fabs( s[ i ] ) / normb ); + if( i > 0 && ! this->checkNextIteration() ) + return i - 1; else + this->refreshSolverMonitor(); + } + + return m; +} + +template< typename Matrix > +void +GMRES< Matrix >:: +compute_residue( VectorViewType r, ConstVectorViewType x, ConstVectorViewType b ) +{ + /**** + * r = M.solve(b - A * x); + */ + if( this->preconditioner ) { + this->matrix->vectorProduct( x, _M_tmp ); + _M_tmp.addVector( b, 1.0, -1.0 ); + this->preconditioner->solve( _M_tmp, r ); + } + else { + this->matrix->vectorProduct( x, r ); + r.addVector( b, 1.0, -1.0 ); + } +} + +template< typename Matrix > +void +GMRES< Matrix >:: +preconditioned_matvec( VectorViewType w, ConstVectorViewType v ) +{ + /**** + * w = M.solve(A * v_i); + */ + if( this->preconditioner ) { + this->matrix->vectorProduct( v, _M_tmp ); + this->preconditioner->solve( _M_tmp, w ); + } + else + this->matrix->vectorProduct( v, w ); +} + +template< typename Matrix > +void +GMRES< Matrix >:: +hauseholder_generate( const int i, + VectorViewType y_i, + ConstVectorViewType z ) +{ + // XXX: the upper-right triangle of Y will be full of zeros, which can be exploited for optimization + if( localOffset == 0 ) { + TNL_ASSERT_LT( i, size, "upper-right triangle of Y is not on rank 0" ); + auto kernel_truncation = [=] __cuda_callable__ ( IndexType j ) mutable { - this->matrix->vectorProduct( x, _r ); - _r.addVector( b, ( RealType ) 1.0, -1.0 ); - beta = _r.lpNorm( ( RealType ) 2.0 ); + if( j < i ) + y_i[ j ] = 0.0; + else + y_i[ j ] = z[ j ]; + }; + ParallelFor< DeviceType >::exec( (IndexType) 0, size, kernel_truncation ); + } + else { + ConstDeviceView z_local = Traits::getLocalVectorView( z ); + DeviceView y_i_local = Traits::getLocalVectorView( y_i ); + y_i_local = z_local; + } + + // norm of the TRUNCATED vector z + const RealType normz = y_i.lpNorm( 2.0 ); + RealType norm_yi = 0; + if( localOffset == 0 ) { + const RealType y_ii = y_i.getElement( i ); + if( y_ii > 0.0 ) + y_i.setElement( i, y_ii + normz ); + else + y_i.setElement( i, y_ii - normz ); + + // compute the norm of the y_i vector; equivalent to this calculation by definition: + // const RealType norm_yi = y_i.lpNorm( 2.0 ); + norm_yi = std::sqrt( 2 * (normz * normz + std::fabs( y_ii ) * normz) ); + } + // no-op if the problem is not distributed + CommunicatorType::Bcast( &norm_yi, 1, 0, Traits::getCommunicationGroup( *this->matrix ) ); + + // XXX: normalization is slower, but more stable +// y_i *= 1.0 / norm_yi; +// const RealType t_i = 2.0; + // assuming it's stable enough... + const RealType t_i = 2.0 / (norm_yi * norm_yi); + + T[ i + i * (restarting_max + 1) ] = t_i; + if( i > 0 ) { + // aux = Y_{i-1}^T * y_i + RealType aux[ i ]; + Containers::Algorithms::ParallelReductionScalarProduct< RealType, RealType > scalarProduct; + Containers::Algorithms::Multireduction< DeviceType >::reduce + ( scalarProduct, + i, + size, + Y.getData(), + ldSize, + Traits::getLocalVectorView( y_i ).getData(), + aux ); + // no-op if the problem is not distributed + CommunicatorType::Allreduce( aux, i, MPI_SUM, Traits::getCommunicationGroup( *this->matrix ) ); + + // [T_i]_{0..i-1} = - T_{i-1} * t_i * aux + for( int k = 0; k < i; k++ ) { + T[ k + i * (restarting_max + 1) ] = 0.0; + for( int j = k; j < i; j++ ) + T[ k + i * (restarting_max + 1) ] -= T[ k + j * (restarting_max + 1) ] * (t_i * aux[ j ]); } - this->setResidue( beta / normb ); + } +} - //cout << " x = " << x << std::endl; - //cout << " beta = " << beta << std::endl; - //cout << "residue = " << beta / normb << std::endl; +template< typename Matrix > +void +GMRES< Matrix >:: +hauseholder_apply_trunc( HostView out, + const int i, + VectorViewType y_i, + ConstVectorViewType z ) +{ + // copy part of y_i to the YL buffer + // The upper (m+1)x(m+1) submatrix of Y is duplicated in the YL buffer, + // which resides on host and is broadcasted from rank 0 to all processes. + HostView YL_i( &YL[ i * (restarting_max + 1) ], restarting_max + 1 ); + Containers::Algorithms::ArrayOperations< Devices::Host, DeviceType >::copyMemory( YL_i.getData(), Traits::getLocalVectorView( y_i ).getData(), YL_i.getSize() ); + // no-op if the problem is not distributed + CommunicatorType::Bcast( YL_i.getData(), YL_i.getSize(), 0, Traits::getCommunicationGroup( *this->matrix ) ); + + // NOTE: aux = t_i * (y_i, z) = 1 since t_i = 2 / ||y_i||^2 and + // (y_i, z) = ||z_trunc||^2 + |z_i| ||z_trunc|| = ||y_i||^2 / 2 +// const RealType aux = T[ i + i * (restarting_max + 1) ] * y_i.scalarProduct( z ); + constexpr RealType aux = 1.0; + if( localOffset == 0 ) { + if( std::is_same< DeviceType, Devices::Host >::value ) { + for( int k = 0; k <= i; k++ ) + out[ k ] = z[ k ] - y_i[ k ] * aux; + } + if( std::is_same< DeviceType, Devices::Cuda >::value ) { + RealType host_z[ i + 1 ]; + Containers::Algorithms::ArrayOperations< Devices::Host, Devices::Cuda >::copyMemory( host_z, Traits::getLocalVectorView( z ).getData(), i + 1 ); + for( int k = 0; k <= i; k++ ) + out[ k ] = host_z[ k ] - YL_i[ k ] * aux; + } + } - // update parameters for the adaptivity of the restarting parameter - ++restart_cycles; - beta_ratio = beta / beta_old; + // no-op if the problem is not distributed + CommunicatorType::Bcast( out.getData(), i + 1, 0, Traits::getCommunicationGroup( *this->matrix ) ); +} + +template< typename Matrix > +void +GMRES< Matrix >:: +hauseholder_cwy( VectorViewType v, + const int i ) +{ + // aux = Y_i^T * e_i + RealType aux[ i + 1 ]; + // the upper (m+1)x(m+1) submatrix of Y is duplicated on host + // (faster access than from the device and it is broadcasted to all processes) + for( int k = 0; k <= i; k++ ) + aux[ k ] = YL[ i + k * (restarting_max + 1) ]; + + // aux = T_i * aux + // Note that T_i is upper triangular, so we can overwrite the aux vector with the result in place + for( int k = 0; k <= i; k++ ) { + RealType aux2 = 0.0; + for( int j = k; j <= i; j++ ) + aux2 += T[ k + j * (restarting_max + 1) ] * aux[ j ]; + aux[ k ] = aux2; } - this->refreshSolverMonitor( true ); - return this->checkConvergence(); + + // v = e_i - Y_i * aux + MatrixOperations< DeviceType >::gemv( size, i + 1, + -1.0, Y.getData(), ldSize, aux, + 0.0, Traits::getLocalVectorView( v ).getData() ); + if( localOffset == 0 ) + v.setElement( i, 1.0 + v.getElement( i ) ); +} + +template< typename Matrix > +void +GMRES< Matrix >:: +hauseholder_cwy_transposed( VectorViewType z, + const int i, + ConstVectorViewType w ) +{ + // aux = Y_i^T * w + RealType aux[ i + 1 ]; + Containers::Algorithms::ParallelReductionScalarProduct< RealType, RealType > scalarProduct; + Containers::Algorithms::Multireduction< DeviceType >::reduce + ( scalarProduct, + i + 1, + size, + Y.getData(), + ldSize, + Traits::getLocalVectorView( w ).getData(), + aux ); + // no-op if the problem is not distributed + Traits::CommunicatorType::Allreduce( aux, i + 1, MPI_SUM, Traits::getCommunicationGroup( *this->matrix ) ); + + // aux = T_i^T * aux + // Note that T_i^T is lower triangular, so we can overwrite the aux vector with the result in place + for( int k = i; k >= 0; k-- ) { + RealType aux2 = 0.0; + for( int j = 0; j <= k; j++ ) + aux2 += T[ j + k * (restarting_max + 1) ] * aux[ j ]; + aux[ k ] = aux2; + } + + // z = w - Y_i * aux + z = w; + MatrixOperations< DeviceType >::gemv( size, i + 1, + -1.0, Y.getData(), ldSize, aux, + 1.0, Traits::getLocalVectorView( z ).getData() ); } template< typename Matrix > - template< typename VectorT > + template< typename Vector > void GMRES< Matrix >:: -update( IndexType k, - IndexType m, - const Containers::Vector< RealType, Devices::Host, IndexType >& H, - const Containers::Vector< RealType, Devices::Host, IndexType >& s, - Containers::Vector< RealType, DeviceType, IndexType >& v, - VectorT& x ) +update( const int k, + const int m, + const HostVector& H, + const HostVector& s, + DeviceVector& V, + Vector& x ) { - Containers::Vector< RealType, Devices::Host, IndexType > y; - y.setSize( m + 1 ); + RealType y[ m + 1 ]; - IndexType i, j; - for( i = 0; i <= m ; i ++ ) + for( int i = 0; i <= m ; i ++ ) y[ i ] = s[ i ]; // Backsolve: - for( i = k; i >= 0; i--) - { - //cout << " y = " << y << std::endl; + for( int i = k; i >= 0; i--) { + if( H[ i + i * ( m + 1 ) ] == 0 ) { +// for( int _i = 0; _i <= i; _i++ ) { +// for( int _j = 0; _j < i; _j++ ) +// std::cout << H[ _i + _j * (m+1) ] << " "; +// std::cout << std::endl; +// } + std::cerr << "H.norm = " << H.lpNorm( 2.0 ) << std::endl; + std::cerr << "s = " << s << std::endl; + std::cerr << "k = " << k << ", m = " << m << std::endl; + throw 1; + } y[ i ] /= H[ i + i * ( m + 1 ) ]; - for( j = i - 1; j >= 0; j--) + for( int j = i - 1; j >= 0; j--) y[ j ] -= H[ j + i * ( m + 1 ) ] * y[ i ]; } - Containers::Vector< RealType, DeviceType, IndexType > vi; - for( i = 0; i <= k; i++) - { - vi.bind( &( v.getData()[ i * this->size ] ), x.getSize() ); - x.addVector( vi, y[ i ] ); - } + // x = V * y + x + MatrixOperations< DeviceType >::gemv( size, k + 1, + 1.0, V.getData(), ldSize, y, + 1.0, Traits::getLocalVectorView( x ).getData() ); } template< typename Matrix > @@ -342,24 +595,20 @@ generatePlaneRotation( RealType& dx, RealType& cs, RealType& sn ) { - if( dy == 0.0 ) - { + if( dy == 0.0 ) { cs = 1.0; sn = 0.0; } - else - if( std::fabs( dy ) > std::fabs( dx ) ) - { - RealType temp = dx / dy; - sn = 1.0 / std::sqrt( 1.0 + temp * temp ); - cs = temp * sn; - } - else - { - RealType temp = dy / dx; - cs = 1.0 / std::sqrt( 1.0 + temp * temp ); - sn = temp * cs; - } + else if( std::fabs( dy ) > std::fabs( dx ) ) { + const RealType temp = dx / dy; + sn = 1.0 / std::sqrt( 1.0 + temp * temp ); + cs = temp * sn; + } + else { + const RealType temp = dy / dx; + cs = 1.0 / std::sqrt( 1.0 + temp * temp ); + sn = temp * cs; + } } template< typename Matrix > @@ -370,28 +619,69 @@ applyPlaneRotation( RealType& dx, RealType& cs, RealType& sn ) { - RealType temp = cs * dx + sn * dy; - dy = cs * dy - sn * dx; + const RealType temp = cs * dx + sn * dy; + dy = cs * dy - sn * dx; dx = temp; } template< typename Matrix > void GMRES< Matrix >:: -setSize( IndexType _size, IndexType m ) +apply_givens_rotations( int i, int m ) { - if( size == _size && restarting_max == m ) - return; - size = _size; - restarting_max = m; - _r.setSize( size ); - w.setSize( size ); - _s.setSize( m + 1 ); - _cs.setSize( m + 1 ); - _sn.setSize( m + 1 ); - _v.setSize( size * ( m + 1 ) ); - _H.setSize( ( m + 1 ) * m ); - _M_tmp.setSize( size ); + for( int k = 0; k < i; k++ ) + applyPlaneRotation( H[ k + i * (m + 1) ], + H[ k + 1 + i * (m + 1) ], + cs[ k ], + sn[ k ] ); + + if( H[ i + 1 + i * (m + 1) ] != 0.0 ) { + generatePlaneRotation( H[ i + i * (m + 1) ], + H[ i + 1 + i * (m + 1) ], + cs[ i ], + sn[ i ]); + applyPlaneRotation( H[ i + i * (m + 1) ], + H[ i + 1 + i * (m + 1) ], + cs[ i ], + sn[ i ]); + applyPlaneRotation( s[ i ], + s[ i + 1 ], + cs[ i ], + sn[ i ] ); + } +} + +template< typename Matrix > +void +GMRES< Matrix >:: +setSize( const VectorViewType& x ) +{ + this->size = Traits::getLocalVectorView( x ).getSize(); + if( std::is_same< DeviceType, Devices::Cuda >::value ) + // align each column to 256 bytes - optimal for CUDA + ldSize = roundToMultiple( size, 256 / sizeof( RealType ) ); + else + // on the host, we add 1 to disrupt the cache false-sharing pattern + ldSize = roundToMultiple( size, 256 / sizeof( RealType ) ) + 1; + localOffset = getLocalOffset( *this->matrix ); + + const int m = restarting_max; + r.setLike( x ); + w.setLike( x ); + _M_tmp.setLike( x ); + V.setSize( ldSize * ( m + 1 ) ); + cs.setSize( m + 1 ); + sn.setSize( m + 1 ); + H.setSize( ( m + 1 ) * m ); + s.setSize( m + 1 ); + + // CWY-specific storage + if( variant == Variant::CWY ) { + z.setLike( x ); + Y.setSize( ldSize * ( m + 1 ) ); + T.setSize( (m + 1) * (m + 1) ); + YL.setSize( (m + 1) * (m + 1) ); + } } } // namespace Linear diff --git a/src/TNL/Solvers/Linear/LinearSolver.h b/src/TNL/Solvers/Linear/LinearSolver.h index 7cf9e9665..66f5f0be0 100644 --- a/src/TNL/Solvers/Linear/LinearSolver.h +++ b/src/TNL/Solvers/Linear/LinearSolver.h @@ -17,9 +17,10 @@ #include #include -#include #include +#include "Traits.h" + namespace TNL { namespace Solvers { namespace Linear { @@ -32,8 +33,8 @@ public: using RealType = typename Matrix::RealType; using DeviceType = typename Matrix::DeviceType; using IndexType = typename Matrix::IndexType; - using VectorViewType = Containers::VectorView< RealType, DeviceType, IndexType >; - using ConstVectorViewType = Containers::VectorView< typename std::add_const< RealType >::type, DeviceType, IndexType >; + using VectorViewType = typename Traits< Matrix >::VectorViewType; + using ConstVectorViewType = typename Traits< Matrix >::ConstVectorViewType; using MatrixType = Matrix; using MatrixPointer = Pointers::SharedPointer< typename std::add_const< MatrixType >::type >; using PreconditionerType = Preconditioners::Preconditioner< MatrixType >; diff --git a/src/TNL/Solvers/Linear/Preconditioners/CMakeLists.txt b/src/TNL/Solvers/Linear/Preconditioners/CMakeLists.txt index 3fe13dd45..13f733c8e 100644 --- a/src/TNL/Solvers/Linear/Preconditioners/CMakeLists.txt +++ b/src/TNL/Solvers/Linear/Preconditioners/CMakeLists.txt @@ -5,6 +5,7 @@ SET( headers Preconditioner.h ILU0_impl.h ILUT.h ILUT_impl.h + TriangularSolve.h ) INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Solvers/Linear/Preconditioners ) diff --git a/src/TNL/Solvers/Linear/Preconditioners/Diagonal.h b/src/TNL/Solvers/Linear/Preconditioners/Diagonal.h index fb5f534f1..0b09814f9 100644 --- a/src/TNL/Solvers/Linear/Preconditioners/Diagonal.h +++ b/src/TNL/Solvers/Linear/Preconditioners/Diagonal.h @@ -36,7 +36,36 @@ public: virtual void update( const MatrixPointer& matrixPointer ) override; - virtual bool solve( ConstVectorViewType b, VectorViewType x ) const override; + virtual void solve( ConstVectorViewType b, VectorViewType x ) const override; + + String getType() const + { + return String( "Diagonal" ); + } + +protected: + VectorType diagonal; +}; + +template< typename Matrix, typename Communicator > +class Diagonal< DistributedContainers::DistributedMatrix< Matrix, Communicator > > +: public Preconditioner< DistributedContainers::DistributedMatrix< Matrix, Communicator > > +{ +public: + using MatrixType = DistributedContainers::DistributedMatrix< Matrix, Communicator >; + using RealType = typename MatrixType::RealType; + using DeviceType = typename MatrixType::DeviceType; + using IndexType = typename MatrixType::IndexType; + using typename Preconditioner< MatrixType >::VectorViewType; + using typename Preconditioner< MatrixType >::ConstVectorViewType; + using typename Preconditioner< MatrixType >::MatrixPointer; + using VectorType = Containers::Vector< RealType, DeviceType, IndexType >; + using LocalVectorViewType = Containers::VectorView< RealType, DeviceType, IndexType >; + using ConstLocalVectorViewType = Containers::VectorView< typename std::add_const< RealType >::type, DeviceType, IndexType >; + + virtual void update( const MatrixPointer& matrixPointer ) override; + + virtual void solve( ConstVectorViewType b, VectorViewType x ) const override; String getType() const { diff --git a/src/TNL/Solvers/Linear/Preconditioners/Diagonal_impl.h b/src/TNL/Solvers/Linear/Preconditioners/Diagonal_impl.h index 897eb006a..42724077e 100644 --- a/src/TNL/Solvers/Linear/Preconditioners/Diagonal_impl.h +++ b/src/TNL/Solvers/Linear/Preconditioners/Diagonal_impl.h @@ -14,107 +14,87 @@ #include "Diagonal.h" +#include + namespace TNL { namespace Solvers { namespace Linear { namespace Preconditioners { -#ifdef HAVE_CUDA -template< typename Real, typename Index, typename Matrix > -__global__ void matrixDiagonalToVectorKernel( const Matrix* matrix, - Real* diagonal, - Index size ) { - Index elementIdx = blockDim. x * blockIdx. x + threadIdx. x; - const Index maxGridSize = blockDim. x * gridDim. x; - while( elementIdx < size ) +template< typename Matrix > +void +Diagonal< Matrix >:: +update( const MatrixPointer& matrixPointer ) +{ + TNL_ASSERT_GT( matrixPointer->getRows(), 0, "empty matrix" ); + TNL_ASSERT_EQ( matrixPointer->getRows(), matrixPointer->getColumns(), "matrix must be square" ); + + diagonal.setSize( matrixPointer->getRows() ); + + VectorViewType diag_view( diagonal ); + const Matrix* kernel_matrix = &matrixPointer.template getData< DeviceType >(); + + auto kernel = [=] __cuda_callable__ ( IndexType i ) mutable { - diagonal[ elementIdx ] = matrix->getElementFast( elementIdx, elementIdx ); - elementIdx += maxGridSize; - } + diag_view[ i ] = kernel_matrix->getElementFast( i, i ); + }; + + ParallelFor< DeviceType >::exec( (IndexType) 0, diagonal.getSize(), kernel ); } -template< typename Real, typename Index > -__global__ void elementwiseVectorDivisionKernel( const Real* left, - const Real* right, - Real* result, - Index size ) +template< typename Matrix > +void +Diagonal< Matrix >:: +solve( ConstVectorViewType b, VectorViewType x ) const { - Index elementIdx = blockDim. x * blockIdx. x + threadIdx. x; - const Index maxGridSize = blockDim. x * gridDim. x; - while( elementIdx < size ) + ConstVectorViewType diag_view( diagonal ); + + auto kernel = [=] __cuda_callable__ ( IndexType i ) mutable { - result[ elementIdx ] = left[ elementIdx ] / right[ elementIdx ]; - elementIdx += maxGridSize; - } + x[ i ] = b[ i ] / diag_view[ i ]; + }; + + ParallelFor< DeviceType >::exec( (IndexType) 0, diagonal.getSize(), kernel ); } -#endif -template< typename Matrix > + +template< typename Matrix, typename Communicator > void -Diagonal< Matrix >:: +Diagonal< DistributedContainers::DistributedMatrix< Matrix, Communicator > >:: update( const MatrixPointer& matrixPointer ) { -// std::cout << getType() << "->setMatrix()" << std::endl; - TNL_ASSERT_GT( matrixPointer->getRows(), 0, "empty matrix" ); TNL_ASSERT_EQ( matrixPointer->getRows(), matrixPointer->getColumns(), "matrix must be square" ); - if( diagonal.getSize() != matrixPointer->getRows() ) - diagonal.setSize( matrixPointer->getRows() ); + diagonal.setSize( matrixPointer->getLocalMatrix().getRows() ); - if( std::is_same< DeviceType, Devices::Host >::value ) - { - for( int i = 0; i < diagonal.getSize(); i++ ) { - diagonal[ i ] = matrixPointer->getElement( i, i ); - } - } - if( std::is_same< DeviceType, Devices::Cuda >::value ) + LocalVectorViewType diag_view( diagonal ); + const MatrixType* kernel_matrix = &matrixPointer.template getData< DeviceType >(); + + auto kernel = [=] __cuda_callable__ ( IndexType i ) mutable { -#ifdef HAVE_CUDA - const IndexType& size = diagonal.getSize(); - dim3 cudaBlockSize( 256 ); - dim3 cudaBlocks; - cudaBlocks.x = min( Devices::Cuda::getMaxGridSize(), Devices::Cuda::getNumberOfBlocks( size, cudaBlockSize.x ) ); - - Devices::Cuda::synchronizeDevice(); - matrixDiagonalToVectorKernel<<< cudaBlocks, cudaBlockSize >>>( - &matrixPointer.template getData< Devices::Cuda >(), - diagonal.getData(), - size ); - TNL_CHECK_CUDA_DEVICE; -#endif - } + const IndexType gi = kernel_matrix->getLocalRowRange().getGlobalIndex( i ); + diag_view[ i ] = kernel_matrix->getLocalMatrix().getElementFast( i, gi ); + }; + + ParallelFor< DeviceType >::exec( (IndexType) 0, diagonal.getSize(), kernel ); } -template< typename Matrix > -bool -Diagonal< Matrix >:: +template< typename Matrix, typename Communicator > +void +Diagonal< DistributedContainers::DistributedMatrix< Matrix, Communicator > >:: solve( ConstVectorViewType b, VectorViewType x ) const { - if( std::is_same< DeviceType, Devices::Host >::value ) - { - for( int i = 0; i < diagonal.getSize(); i++ ) { - x[ i ] = b[ i ] / diagonal[ i ]; - } - } - if( std::is_same< DeviceType, Devices::Cuda >::value ) + ConstLocalVectorViewType diag_view( diagonal ); + const auto b_view = b.getLocalVectorView(); + auto x_view = x.getLocalVectorView(); + + auto kernel = [=] __cuda_callable__ ( IndexType i ) mutable { -#ifdef HAVE_CUDA - const IndexType& size = diagonal.getSize(); - dim3 cudaBlockSize( 256 ); - dim3 cudaBlocks; - cudaBlocks.x = min( Devices::Cuda::getMaxGridSize(), Devices::Cuda::getNumberOfBlocks( size, cudaBlockSize.x ) ); - - elementwiseVectorDivisionKernel<<< cudaBlocks, cudaBlockSize >>>( - b.getData(), - diagonal.getData(), - x.getData(), - size ); - - TNL_CHECK_CUDA_DEVICE; -#endif - } - return true; + x_view[ i ] = b_view[ i ] / diag_view[ i ]; + }; + + ParallelFor< DeviceType >::exec( (IndexType) 0, diagonal.getSize(), kernel ); } } // namespace Preconditioners diff --git a/src/TNL/Solvers/Linear/Preconditioners/ILU0.h b/src/TNL/Solvers/Linear/Preconditioners/ILU0.h index b94d79052..ff7a8f775 100644 --- a/src/TNL/Solvers/Linear/Preconditioners/ILU0.h +++ b/src/TNL/Solvers/Linear/Preconditioners/ILU0.h @@ -12,12 +12,11 @@ #pragma once -#include - #include "Preconditioner.h" #include #include +#include #if defined(HAVE_CUDA) && defined(HAVE_CUSPARSE) #include @@ -59,11 +58,25 @@ public: virtual void update( const MatrixPointer& matrixPointer ) override; - virtual bool solve( ConstVectorViewType b, VectorViewType x ) const override; + virtual void solve( ConstVectorViewType b, VectorViewType x ) const override; protected: - Matrices::CSR< RealType, DeviceType, IndexType > L; - Matrices::CSR< RealType, DeviceType, IndexType > U; + // The factors L and U are stored separately and the rows of U are reversed. + Matrices::CSR< RealType, DeviceType, IndexType > L, U; + + // Specialized methods to distinguish between normal and distributed matrices + // in the implementation. + template< typename M > + static IndexType getMinColumn( const M& m ) + { + return 0; + } + + template< typename M > + static IndexType getMinColumn( const DistributedContainers::DistributedMatrix< M >& m ) + { + return m.getLocalRowRange().getBegin(); + } }; template< typename Matrix > @@ -87,7 +100,7 @@ public: virtual void update( const MatrixPointer& matrixPointer ) override; - virtual bool solve( ConstVectorViewType b, VectorViewType x ) const override; + virtual void solve( ConstVectorViewType b, VectorViewType x ) const override; ~ILU0_impl() { @@ -97,9 +110,14 @@ public: #endif } + // must be public because nvcc does not allow extended lambdas in private or protected regions + void allocate_LU(); + void copy_triangular_factors(); protected: + #if defined(HAVE_CUDA) && defined(HAVE_CUSPARSE) - Matrices::CSR< RealType, DeviceType, IndexType > A; + using CSR = Matrices::CSR< RealType, DeviceType, IndexType >; + Pointers::UniquePointer< CSR > A, L, U; Containers::Vector< RealType, DeviceType, IndexType > y; cusparseHandle_t handle; @@ -114,6 +132,9 @@ protected: const cusparseSolvePolicy_t policy_A = CUSPARSE_SOLVE_POLICY_USE_LEVEL; const cusparseSolvePolicy_t policy_L = CUSPARSE_SOLVE_POLICY_USE_LEVEL; const cusparseSolvePolicy_t policy_U = CUSPARSE_SOLVE_POLICY_USE_LEVEL; +// const cusparseSolvePolicy_t policy_A = CUSPARSE_SOLVE_POLICY_NO_LEVEL; +// const cusparseSolvePolicy_t policy_L = CUSPARSE_SOLVE_POLICY_NO_LEVEL; +// const cusparseSolvePolicy_t policy_U = CUSPARSE_SOLVE_POLICY_NO_LEVEL; const cusparseOperation_t trans_L = CUSPARSE_OPERATION_NON_TRANSPOSE; const cusparseOperation_t trans_U = CUSPARSE_OPERATION_NON_TRANSPOSE; @@ -150,25 +171,31 @@ protected: } pBuffer.reset(); } +#endif +}; - // TODO: extend Matrices::copySparseMatrix accordingly - template< typename MatrixT, - typename = typename std::enable_if< ! std::is_same< DeviceType, typename MatrixT::DeviceType >::value >::type > - void copyMatrix( const MatrixT& matrix ) +template< typename Matrix, typename Communicator > +class ILU0_impl< DistributedContainers::DistributedMatrix< Matrix, Communicator >, double, Devices::Cuda, int > +: public Preconditioner< DistributedContainers::DistributedMatrix< Matrix, Communicator > > +{ + using MatrixType = DistributedContainers::DistributedMatrix< Matrix, Communicator >; +public: + using RealType = double; + using DeviceType = Devices::Cuda; + using IndexType = int; + using typename Preconditioner< MatrixType >::VectorViewType; + using typename Preconditioner< MatrixType >::ConstVectorViewType; + using typename Preconditioner< MatrixType >::MatrixPointer; + + virtual void update( const MatrixPointer& matrixPointer ) override { - typename MatrixT::CudaType A_tmp; - A_tmp = matrix; - Matrices::copySparseMatrix( A, A_tmp ); + throw std::runtime_error("ILU0 is not implemented yet for CUDA and distributed matrices."); } - template< typename MatrixT, - typename = typename std::enable_if< std::is_same< DeviceType, typename MatrixT::DeviceType >::value >::type, - typename = void > - void copyMatrix( const MatrixT& matrix ) + virtual void solve( ConstVectorViewType b, VectorViewType x ) const override { - Matrices::copySparseMatrix( A, matrix ); + throw std::runtime_error("ILU0 is not implemented yet for CUDA and distributed matrices."); } -#endif }; template< typename Matrix, typename Real, typename Index > @@ -188,7 +215,7 @@ public: throw std::runtime_error("Not Iplemented yet for MIC"); } - virtual bool solve( ConstVectorViewType b, VectorViewType x ) const override + virtual void solve( ConstVectorViewType b, VectorViewType x ) const override { throw std::runtime_error("Not Iplemented yet for MIC"); } diff --git a/src/TNL/Solvers/Linear/Preconditioners/ILU0_impl.h b/src/TNL/Solvers/Linear/Preconditioners/ILU0_impl.h index 2b2244df3..33f44e60c 100644 --- a/src/TNL/Solvers/Linear/Preconditioners/ILU0_impl.h +++ b/src/TNL/Solvers/Linear/Preconditioners/ILU0_impl.h @@ -13,8 +13,10 @@ #pragma once #include "ILU0.h" +#include "TriangularSolve.h" #include +#include namespace TNL { namespace Solvers { @@ -29,30 +31,32 @@ update( const MatrixPointer& matrixPointer ) TNL_ASSERT_GT( matrixPointer->getRows(), 0, "empty matrix" ); TNL_ASSERT_EQ( matrixPointer->getRows(), matrixPointer->getColumns(), "matrix must be square" ); - const IndexType N = matrixPointer->getRows(); + const auto& localMatrix = Traits< Matrix >::getLocalMatrix( *matrixPointer ); + const IndexType N = localMatrix.getRows(); + const IndexType minColumn = getMinColumn( *matrixPointer ); L.setDimensions( N, N ); U.setDimensions( N, N ); // copy row lengths - typename decltype(L)::CompressedRowLengthsVector L_rowLengths; - typename decltype(U)::CompressedRowLengthsVector U_rowLengths; - L_rowLengths.setSize( N ); - U_rowLengths.setSize( N ); + typename decltype(L)::CompressedRowLengthsVector L_rowLengths( N ); + typename decltype(U)::CompressedRowLengthsVector U_rowLengths( N ); for( IndexType i = 0; i < N; i++ ) { - const auto row = matrixPointer->getRow( i ); - const auto max_length = matrixPointer->getRowLength( i ); - IndexType L_entries = 0; - IndexType U_entries = 0; - for( IndexType j = 0; j < max_length; j++ ) { - const auto column = row.getElementColumn( j ); - if( column < i ) - L_entries++; - else if( column < N ) - U_entries++; - else - break; - } + const auto row = localMatrix.getRow( i ); + const auto max_length = row.getLength(); + IndexType L_entries = 0; + IndexType U_entries = 0; + for( IndexType j = 0; j < max_length; j++ ) { + const auto column = row.getElementColumn( j ); + if( column < minColumn ) + continue; + if( column < i + minColumn ) + L_entries++; + else if( column < N + minColumn ) + U_entries++; + else + break; + } L_rowLengths[ i ] = L_entries; U_rowLengths[ N - 1 - i ] = U_entries; } @@ -63,10 +67,23 @@ update( const MatrixPointer& matrixPointer ) // The factors L and U are stored separately and the rows of U are reversed. for( IndexType i = 0; i < N; i++ ) { // copy all non-zero entries from A into L and U - const auto max_length = matrixPointer->getRowLength( i ); - IndexType columns[ max_length ]; - RealType values[ max_length ]; - matrixPointer->getRowFast( i, columns, values ); + const auto max_length = localMatrix.getRowLength( i ); + IndexType all_columns[ max_length ]; + RealType all_values[ max_length ]; + localMatrix.getRowFast( i, all_columns, all_values ); + + // skip non-local elements + IndexType* columns = all_columns; + RealType* values = all_values; + while( columns[0] < minColumn ) { + columns++; + values++; + } + + // update column column indices + if( minColumn > 0 ) + for( IndexType c_j = 0; c_j < max_length; c_j++ ) + all_columns[ c_j ] -= minColumn; const auto L_entries = L_rowLengths[ i ]; const auto U_entries = U_rowLengths[ N - 1 - i ]; @@ -103,52 +120,18 @@ update( const MatrixPointer& matrixPointer ) } template< typename Matrix, typename Real, typename Index > -bool +void ILU0_impl< Matrix, Real, Devices::Host, Index >:: -solve( ConstVectorViewType b, VectorViewType x ) const +solve( ConstVectorViewType _b, VectorViewType _x ) const { - TNL_ASSERT_EQ( b.getSize(), L.getRows(), "wrong size of the right hand side" ); - TNL_ASSERT_EQ( x.getSize(), L.getRows(), "wrong size of the solution vector" ); - - const IndexType N = x.getSize(); + const auto b = Traits< Matrix >::getLocalVectorView( _b ); + auto x = Traits< Matrix >::getLocalVectorView( _x ); // Step 1: solve y from Ly = b - for( IndexType i = 0; i < N; i++ ) { - x[ i ] = b[ i ]; - - const auto L_entries = L.getRowLength( i ); - - // this condition is to avoid segfaults on empty L.getRow( i ) - if( L_entries > 0 ) { - const auto L_i = L.getRow( i ); - - // loop for j = 0, ..., i - 1; but only over the non-zero entries - for( IndexType c_j = 0; c_j < L_entries; c_j++ ) { - const auto j = L_i.getElementColumn( c_j ); - x[ i ] -= L_i.getElementValue( c_j ) * x[ j ]; - } - } - } + triangularSolveLower< true >( L, x, b ); // Step 2: solve x from Ux = y - for( IndexType i = N - 1; i >= 0; i-- ) { - const IndexType U_idx = N - 1 - i; - - const auto U_entries = U.getRowLength( U_idx ); - const auto U_i = U.getRow( U_idx ); - - const auto U_ii = U_i.getElementValue( 0 ); - - // loop for j = i+1, ..., N-1; but only over the non-zero entries - for( IndexType c_j = 1; c_j < U_entries ; c_j++ ) { - const auto j = U_i.getElementColumn( c_j ); - x[ i ] -= U_i.getElementValue( c_j ) * x[ j ]; - } - - x[ i ] /= U_ii; - } - - return true; + triangularSolveUpper< true, true >( U, x, x ); } @@ -164,12 +147,16 @@ update( const MatrixPointer& matrixPointer ) // Note: the decomposition will be in-place, matrices L and U will have the // storage of A - copyMatrix( *matrixPointer ); + copySparseMatrix( *A, *matrixPointer ); - const int m = A.getRows(); - const int nnz = A.getValues().getSize(); + allocate_LU(); - y.setSize( m ); + const int N = A->getRows(); + const int nnz_A = A->getValues().getSize(); + const int nnz_L = L->getValues().getSize(); + const int nnz_U = U->getValues().getSize(); + + y.setSize( N ); // create matrix descriptors cusparseCreateMatDescr( &descr_A ); @@ -188,36 +175,40 @@ update( const MatrixPointer& matrixPointer ) cusparseSetMatFillMode( descr_U, CUSPARSE_FILL_MODE_UPPER ); cusparseSetMatDiagType( descr_U, CUSPARSE_DIAG_TYPE_NON_UNIT ); + TNL_CHECK_CUDA_DEVICE; + // create info structures cusparseCreateCsrilu02Info( &info_A ); cusparseCreateCsrsv2Info( &info_L ); cusparseCreateCsrsv2Info( &info_U ); + TNL_CHECK_CUDA_DEVICE; // query how much memory will be needed in csrilu02 and csrsv2, and allocate the buffer int pBufferSize_A, pBufferSize_L, pBufferSize_U; - cusparseDcsrilu02_bufferSize( handle, m, nnz, descr_A, - A.getValues().getData(), - A.getRowPointers().getData(), - A.getColumnIndexes().getData(), + cusparseDcsrilu02_bufferSize( handle, N, nnz_A, descr_A, + A->getValues().getData(), + A->getRowPointers().getData(), + A->getColumnIndexes().getData(), info_A, &pBufferSize_A ); - cusparseDcsrsv2_bufferSize( handle, trans_L, m, nnz, descr_L, - A.getValues().getData(), - A.getRowPointers().getData(), - A.getColumnIndexes().getData(), + cusparseDcsrsv2_bufferSize( handle, trans_L, N, nnz_L, descr_L, + L->getValues().getData(), + L->getRowPointers().getData(), + L->getColumnIndexes().getData(), info_L, &pBufferSize_L ); - cusparseDcsrsv2_bufferSize( handle, trans_U, m, nnz, descr_U, - A.getValues().getData(), - A.getRowPointers().getData(), - A.getColumnIndexes().getData(), + cusparseDcsrsv2_bufferSize( handle, trans_U, N, nnz_U, descr_U, + U->getValues().getData(), + U->getRowPointers().getData(), + U->getColumnIndexes().getData(), info_U, &pBufferSize_U ); + TNL_CHECK_CUDA_DEVICE; const int pBufferSize = max( pBufferSize_A, max( pBufferSize_L, pBufferSize_U ) ); pBuffer.setSize( pBufferSize ); // Symbolic analysis of the incomplete LU decomposition - cusparseDcsrilu02_analysis( handle, m, nnz, descr_A, - A.getValues().getData(), - A.getRowPointers().getData(), - A.getColumnIndexes().getData(), + cusparseDcsrilu02_analysis( handle, N, nnz_A, descr_A, + A->getValues().getData(), + A->getRowPointers().getData(), + A->getColumnIndexes().getData(), info_A, policy_A, pBuffer.getData() ); int structural_zero; cusparseStatus_t @@ -226,26 +217,27 @@ update( const MatrixPointer& matrixPointer ) std::cerr << "A(" << structural_zero << ", " << structural_zero << ") is missing." << std::endl; throw 1; } + TNL_CHECK_CUDA_DEVICE; // Analysis for the triangular solves for L and U // Trick: the lower (upper) triangular part of A has the same sparsity // pattern as L (U), so we can do the analysis for csrsv2 on the matrix A. - cusparseDcsrsv2_analysis( handle, trans_L, m, nnz, descr_L, - A.getValues().getData(), - A.getRowPointers().getData(), - A.getColumnIndexes().getData(), - info_L, policy_L, pBuffer.getData() ); - cusparseDcsrsv2_analysis( handle, trans_U, m, nnz, descr_U, - A.getValues().getData(), - A.getRowPointers().getData(), - A.getColumnIndexes().getData(), - info_U, policy_U, pBuffer.getData() ); +// cusparseDcsrsv2_analysis( handle, trans_L, N, nnz_A, descr_L, +// A->getValues().getData(), +// A->getRowPointers().getData(), +// A->getColumnIndexes().getData(), +// info_L, policy_L, pBuffer.getData() ); +// cusparseDcsrsv2_analysis( handle, trans_U, N, nnz_A, descr_U, +// A->getValues().getData(), +// A->getRowPointers().getData(), +// A->getColumnIndexes().getData(), +// info_U, policy_U, pBuffer.getData() ); // Numerical incomplete LU decomposition - cusparseDcsrilu02( handle, m, nnz, descr_A, - A.getValues().getData(), - A.getRowPointers().getData(), - A.getColumnIndexes().getData(), + cusparseDcsrilu02( handle, N, nnz_A, descr_A, + A->getValues().getData(), + A->getRowPointers().getData(), + A->getColumnIndexes().getData(), info_A, policy_A, pBuffer.getData() ); int numerical_zero; status = cusparseXcsrilu02_zeroPivot( handle, info_A, &numerical_zero ); @@ -253,6 +245,72 @@ update( const MatrixPointer& matrixPointer ) std::cerr << "A(" << numerical_zero << ", " << numerical_zero << ") is zero." << std::endl; throw 1; } + TNL_CHECK_CUDA_DEVICE; + + // Split the factors L and U into separate storages + copy_triangular_factors(); + + // Analysis for the triangular solves for L and U + cusparseDcsrsv2_analysis( handle, trans_L, N, nnz_L, descr_L, + L->getValues().getData(), + L->getRowPointers().getData(), + L->getColumnIndexes().getData(), + info_L, policy_L, pBuffer.getData() ); + cusparseDcsrsv2_analysis( handle, trans_U, N, nnz_U, descr_U, + U->getValues().getData(), + U->getRowPointers().getData(), + U->getColumnIndexes().getData(), + info_U, policy_U, pBuffer.getData() ); + TNL_CHECK_CUDA_DEVICE; +#else + throw std::runtime_error("The program was not compiled with the CUSPARSE library. Pass -DHAVE_CUSPARSE -lcusparse to the compiler."); +#endif +#else + throw Exceptions::CudaSupportMissing(); +#endif +} + +template< typename Matrix > +void +ILU0_impl< Matrix, double, Devices::Cuda, int >:: +allocate_LU() +{ +#ifdef HAVE_CUDA +#ifdef HAVE_CUSPARSE + const int N = A->getRows(); + L->setDimensions( N, N ); + U->setDimensions( N, N ); + + // extract raw pointer + Devices::Cuda::synchronizeDevice(); + const CSR* kernel_A = &A.template getData< DeviceType >(); + + // copy row lengths + typename CSR::CompressedRowLengthsVector L_rowLengths( N ); + typename CSR::CompressedRowLengthsVector U_rowLengths( N ); + Containers::VectorView< typename decltype(L_rowLengths)::RealType, DeviceType, IndexType > L_rowLengths_view( L_rowLengths ); + Containers::VectorView< typename decltype(U_rowLengths)::RealType, DeviceType, IndexType > U_rowLengths_view( U_rowLengths ); + auto kernel_copy_row_lengths = [=] __cuda_callable__ ( IndexType i ) mutable + { + const auto row = kernel_A->getRow( i ); + const int max_length = row.getLength(); + int L_entries = 0; + int U_entries = 0; + for( int c_j = 0; c_j < max_length; c_j++ ) { + const IndexType j = row.getElementColumn( c_j ); + if( j < i ) + L_entries++; + else if( j < N ) + U_entries++; + else + break; + } + L_rowLengths_view[ i ] = L_entries; + U_rowLengths_view[ i ] = U_entries; + }; + ParallelFor< DeviceType >::exec( (IndexType) 0, N, kernel_copy_row_lengths ); + L->setCompressedRowLengths( L_rowLengths ); + U->setCompressedRowLengths( U_rowLengths ); #else throw std::runtime_error("The program was not compiled with the CUSPARSE library. Pass -DHAVE_CUSPARSE -lcusparse to the compiler."); #endif @@ -262,36 +320,76 @@ update( const MatrixPointer& matrixPointer ) } template< typename Matrix > -bool +void +ILU0_impl< Matrix, double, Devices::Cuda, int >:: +copy_triangular_factors() +{ +#ifdef HAVE_CUDA +#ifdef HAVE_CUSPARSE + const int N = A->getRows(); + + // extract raw pointers + Devices::Cuda::synchronizeDevice(); + CSR* kernel_L = &L.template modifyData< DeviceType >(); + CSR* kernel_U = &U.template modifyData< DeviceType >(); + const CSR* kernel_A = &A.template getData< DeviceType >(); + + // copy values from A to L and U + auto kernel_copy_values = [=] __cuda_callable__ ( IndexType i ) mutable + { + const auto row = kernel_A->getRow( i ); + const int max_length = row.getLength(); + for( int c_j = 0; c_j < max_length; c_j++ ) { + const IndexType j = row.getElementColumn( c_j ); + if( j < i ) + kernel_L->setElementFast( i, j, row.getElementValue( c_j ) ); + else if( j < N ) + kernel_U->setElementFast( i, j, row.getElementValue( c_j ) ); + else + break; + } + }; + ParallelFor< DeviceType >::exec( (IndexType) 0, N, kernel_copy_values ); +#else + throw std::runtime_error("The program was not compiled with the CUSPARSE library. Pass -DHAVE_CUSPARSE -lcusparse to the compiler."); +#endif +#else + throw Exceptions::CudaSupportMissing(); +#endif +} + +template< typename Matrix > +void ILU0_impl< Matrix, double, Devices::Cuda, int >:: solve( ConstVectorViewType b, VectorViewType x ) const { #ifdef HAVE_CUDA #ifdef HAVE_CUSPARSE - const int m = A.getRows(); - const int nnz = A.getValues().getSize(); + const int N = A->getRows(); + const int nnz_L = L->getValues().getSize(); + const int nnz_U = U->getValues().getSize(); // Step 1: solve y from Ly = b - cusparseDcsrsv2_solve( handle, trans_L, m, nnz, &alpha, descr_L, - A.getValues().getData(), - A.getRowPointers().getData(), - A.getColumnIndexes().getData(), + cusparseDcsrsv2_solve( handle, trans_L, N, nnz_L, &alpha, descr_L, + L->getValues().getData(), + L->getRowPointers().getData(), + L->getColumnIndexes().getData(), info_L, b.getData(), (RealType*) y.getData(), policy_L, (void*) pBuffer.getData() ); // Step 2: solve x from Ux = y - cusparseDcsrsv2_solve( handle, trans_U, m, nnz, &alpha, descr_U, - A.getValues().getData(), - A.getRowPointers().getData(), - A.getColumnIndexes().getData(), + cusparseDcsrsv2_solve( handle, trans_U, N, nnz_U, &alpha, descr_U, + U->getValues().getData(), + U->getRowPointers().getData(), + U->getColumnIndexes().getData(), info_U, y.getData(), x.getData(), policy_U, (void*) pBuffer.getData() ); - return true; + TNL_CHECK_CUDA_DEVICE; #else throw std::runtime_error("The program was not compiled with the CUSPARSE library. Pass -DHAVE_CUSPARSE -lcusparse to the compiler."); #endif diff --git a/src/TNL/Solvers/Linear/Preconditioners/ILUT.h b/src/TNL/Solvers/Linear/Preconditioners/ILUT.h index f9147c7b8..5f1654ecf 100644 --- a/src/TNL/Solvers/Linear/Preconditioners/ILUT.h +++ b/src/TNL/Solvers/Linear/Preconditioners/ILUT.h @@ -64,15 +64,28 @@ public: virtual void update( const MatrixPointer& matrixPointer ) override; - virtual bool solve( ConstVectorViewType b, VectorViewType x ) const override; + virtual void solve( ConstVectorViewType b, VectorViewType x ) const override; protected: Index p = 0; Real tau = 1e-4; // The factors L and U are stored separately and the rows of U are reversed. - Matrices::CSR< RealType, DeviceType, IndexType > L; - Matrices::CSR< RealType, DeviceType, IndexType > U; + Matrices::CSR< RealType, DeviceType, IndexType > L, U; + + // Specialized methods to distinguish between normal and distributed matrices + // in the implementation. + template< typename M > + static IndexType getMinColumn( const M& m ) + { + return 0; + } + + template< typename M > + static IndexType getMinColumn( const DistributedContainers::DistributedMatrix< M >& m ) + { + return m.getLocalRowRange().getBegin(); + } }; template< typename Matrix, typename Real, typename Index > @@ -92,7 +105,7 @@ public: throw std::runtime_error("Not Iplemented yet for CUDA"); } - virtual bool solve( ConstVectorViewType b, VectorViewType x ) const override + virtual void solve( ConstVectorViewType b, VectorViewType x ) const override { throw std::runtime_error("Not Iplemented yet for CUDA"); } @@ -115,7 +128,7 @@ public: throw std::runtime_error("Not Iplemented yet for MIC"); } - virtual bool solve( ConstVectorViewType b, VectorViewType x ) const override + virtual void solve( ConstVectorViewType b, VectorViewType x ) const override { throw std::runtime_error("Not Iplemented yet for MIC"); } diff --git a/src/TNL/Solvers/Linear/Preconditioners/ILUT_impl.h b/src/TNL/Solvers/Linear/Preconditioners/ILUT_impl.h index bb08ffb14..a1735e9e6 100644 --- a/src/TNL/Solvers/Linear/Preconditioners/ILUT_impl.h +++ b/src/TNL/Solvers/Linear/Preconditioners/ILUT_impl.h @@ -13,8 +13,11 @@ #pragma once #include +#include #include "ILUT.h" +#include "TriangularSolve.h" + #include namespace TNL { @@ -41,31 +44,33 @@ update( const MatrixPointer& matrixPointer ) TNL_ASSERT_GT( matrixPointer->getRows(), 0, "empty matrix" ); TNL_ASSERT_EQ( matrixPointer->getRows(), matrixPointer->getColumns(), "matrix must be square" ); - const IndexType N = matrixPointer->getRows(); + const auto& localMatrix = Traits< Matrix >::getLocalMatrix( *matrixPointer ); + const IndexType N = localMatrix.getRows(); + const IndexType minColumn = getMinColumn( *matrixPointer ); L.setDimensions( N, N ); U.setDimensions( N, N ); - Timer timer_total, timer_rowlengths, timer_copy_into_w, timer_k_loop, timer_dropping, timer_copy_into_LU; +// Timer timer_total, timer_rowlengths, timer_copy_into_w, timer_k_loop, timer_heap_construct, timer_heap_extract, timer_copy_into_LU, timer_reset; - timer_total.start(); +// timer_total.start(); // compute row lengths - timer_rowlengths.start(); - typename decltype(L)::CompressedRowLengthsVector L_rowLengths; - typename decltype(U)::CompressedRowLengthsVector U_rowLengths; - L_rowLengths.setSize( N ); - U_rowLengths.setSize( N ); +// timer_rowlengths.start(); + typename decltype(L)::CompressedRowLengthsVector L_rowLengths( N ); + typename decltype(U)::CompressedRowLengthsVector U_rowLengths( N ); for( IndexType i = 0; i < N; i++ ) { - const auto row = matrixPointer->getRow( i ); - const auto max_length = matrixPointer->getRowLength( i ); + const auto row = localMatrix.getRow( i ); + const auto max_length = localMatrix.getRowLength( i ); IndexType L_entries = 0; IndexType U_entries = 0; for( IndexType j = 0; j < max_length; j++ ) { const auto column = row.getElementColumn( j ); - if( column < i ) + if( column < minColumn ) + continue; + if( column < i + minColumn ) L_entries++; - else if( column < N ) + else if( column < N + minColumn ) U_entries++; else break; @@ -76,7 +81,7 @@ update( const MatrixPointer& matrixPointer ) } L.setCompressedRowLengths( L_rowLengths ); U.setCompressedRowLengths( U_rowLengths ); - timer_rowlengths.stop(); +// timer_rowlengths.stop(); // intermediate full vector for the i-th row of A VectorType w; @@ -84,7 +89,6 @@ update( const MatrixPointer& matrixPointer ) w.setValue( 0.0 ); // intermediate vectors for sorting and keeping only the largest values -// using Pair = std::pair< IndexType, RealType >; struct Triplet { IndexType column; RealType value; @@ -96,41 +100,48 @@ update( const MatrixPointer& matrixPointer ) auto cmp_column = []( const Triplet& a, const Triplet& b ){ return a.column < b.column; }; std::vector< Triplet > values_L, values_U; -// std::cout << "N = " << N << std::endl; - // Incomplete LU factorization with threshold // (see Saad - Iterative methods for sparse linear systems, section 10.4) for( IndexType i = 0; i < N; i++ ) { - const auto max_length = matrixPointer->getRowLength( i ); - const auto A_i = matrixPointer->getRow( i ); + const auto max_length = localMatrix.getRowLength( i ); + const auto A_i = localMatrix.getRow( i ); RealType A_i_norm = 0.0; + // set of indices where w_k is non-zero (i.e. {k: w_k != 0}) + std::set< IndexType > w_k_set; + // copy A_i into the full vector w - timer_copy_into_w.start(); +// timer_copy_into_w.start(); for( IndexType c_j = 0; c_j < max_length; c_j++ ) { - const auto j = A_i.getElementColumn( c_j ); + auto j = A_i.getElementColumn( c_j ); + if( minColumn > 0 ) { + // skip non-local elements + if( j < minColumn ) continue; + j -= minColumn; + } // handle ellpack dummy entries if( j >= N ) break; w[ j ] = A_i.getElementValue( c_j ); // running computation of norm A_i_norm += w[ j ] * w[ j ]; + + w_k_set.insert( j ); } - timer_copy_into_w.stop(); +// timer_copy_into_w.stop(); // compute relative tolerance A_i_norm = std::sqrt( A_i_norm ); const RealType tau_i = tau * A_i_norm; // loop for k = 0, ..., i - 1; but only over the non-zero entries of w - timer_k_loop.start(); - for( IndexType k = 0; k < i; k++ ) { - RealType w_k = w[ k ]; - if( w_k == 0.0 ) - continue; +// timer_k_loop.start(); + for( const IndexType k : w_k_set ) { + if( k >= i ) + break; - w_k /= matrixPointer->getElementFast( k, k ); + RealType w_k = w[ k ] / localMatrix.getElementFast( k, k + minColumn ); // apply dropping rule to w_k if( std::abs( w_k ) < tau_i ) @@ -144,36 +155,42 @@ update( const MatrixPointer& matrixPointer ) // loop for j = 0, ..., N-1; but only over the non-zero entries for( Index c_j = 0; c_j < U_rowLengths[ N - 1 - k ]; c_j++ ) { const auto j = U_k.getElementColumn( c_j ); + // skip dropped entries if( j >= N ) break; w[ j ] -= w_k * U_k.getElementValue( c_j ); + + // add non-zero to the w_k_set + w_k_set.insert( j ); } } } - timer_k_loop.stop(); +// timer_k_loop.stop(); // apply dropping rule to the row w // (we drop all values under threshold and keep nl(i) + p largest values in L // and nu(i) + p largest values in U; see Saad (2003) for reference) - // TODO: refactoring!!! (use the quick-split strategy, constructing the heap is not necessary) - timer_dropping.start(); - for( IndexType j = 0; j < N; j++ ) { + + // construct heaps with the values in the L and U parts separately +// timer_heap_construct.start(); + for( const IndexType j : w_k_set ) { const RealType w_j_abs = std::abs( w[ j ] ); // ignore small values if( w_j_abs < tau_i ) continue; // push into the heaps for L or U - if( j < i ) { + if( j < i ) heap_L.push_back( Triplet( j, w[ j ], w_j_abs ) ); - std::push_heap( heap_L.begin(), heap_L.end(), cmp_abs_value ); - } - else { + else heap_U.push_back( Triplet( j, w[ j ], w_j_abs ) ); - std::push_heap( heap_U.begin(), heap_U.end(), cmp_abs_value ); - } } + std::make_heap( heap_L.begin(), heap_L.end(), cmp_abs_value ); + std::make_heap( heap_U.begin(), heap_U.end(), cmp_abs_value ); +// timer_heap_construct.stop(); + // extract values for L and U - for( IndexType c_j = 0; c_j < L_rowLengths[ i ] && c_j < heap_L.size(); c_j++ ) { +// timer_heap_extract.start(); + for( IndexType c_j = 0; c_j < L_rowLengths[ i ] && c_j < (IndexType) heap_L.size(); c_j++ ) { // move the largest to the end std::pop_heap( heap_L.begin(), heap_L.end(), cmp_abs_value ); // move the triplet from one vector into another @@ -181,7 +198,7 @@ update( const MatrixPointer& matrixPointer ) heap_L.pop_back(); values_L.push_back( largest ); } - for( IndexType c_j = 0; c_j < U_rowLengths[ N - 1 - i ] && c_j < heap_U.size(); c_j++ ) { + for( IndexType c_j = 0; c_j < U_rowLengths[ N - 1 - i ] && c_j < (IndexType) heap_U.size(); c_j++ ) { // move the largest to the end std::pop_heap( heap_U.begin(), heap_U.end(), cmp_abs_value ); // move the triplet from one vector into another @@ -189,108 +206,74 @@ update( const MatrixPointer& matrixPointer ) heap_U.pop_back(); values_U.push_back( largest ); } - // sort by column index to make it insertable into the sparse matrix - std::sort( values_L.begin(), values_L.end(), cmp_column ); - std::sort( values_U.begin(), values_U.end(), cmp_column ); - timer_dropping.stop(); +// timer_heap_extract.stop(); // std::cout << "i = " << i << ", L_rowLengths[ i ] = " << L_rowLengths[ i ] << ", U_rowLengths[ i ] = " << U_rowLengths[ N - 1 - i ] << std::endl; - timer_copy_into_LU.start(); +// timer_copy_into_LU.start(); + + // sort by column index to make it insertable into the sparse matrix + std::sort( values_L.begin(), values_L.end(), cmp_column ); + std::sort( values_U.begin(), values_U.end(), cmp_column ); // the row L_i might be empty if( values_L.size() ) { // L_ij = w_j for j = 0, ..., i - 1 auto L_i = L.getRow( i ); - for( IndexType c_j = 0; c_j < values_L.size(); c_j++ ) { + for( IndexType c_j = 0; c_j < (IndexType) values_L.size(); c_j++ ) { const auto j = values_L[ c_j ].column; -// std::cout << "c_j = " << c_j << ", j = " << j << std::endl; L_i.setElement( c_j, j, values_L[ c_j ].value ); } } // U_ij = w_j for j = i, ..., N - 1 auto U_i = U.getRow( N - 1 - i ); - for( IndexType c_j = 0; c_j < values_U.size(); c_j++ ) { + for( IndexType c_j = 0; c_j < (IndexType) values_U.size(); c_j++ ) { const auto j = values_U[ c_j ].column; -// std::cout << "c_j = " << c_j << ", j = " << j << std::endl; U_i.setElement( c_j, j, values_U[ c_j ].value ); } - timer_copy_into_LU.stop(); +// timer_copy_into_LU.stop(); // reset w - w.setValue( 0.0 ); +// timer_reset.start(); + for( const IndexType j : w_k_set ) + w[ j ] = 0.0; heap_L.clear(); heap_U.clear(); values_L.clear(); values_U.clear(); +// timer_reset.stop(); } - timer_total.stop(); - - std::cout << "ILUT::update statistics:\n"; - std::cout << "\ttimer_total: " << timer_total.getRealTime() << " s\n"; - std::cout << "\ttimer_rowlengths: " << timer_rowlengths.getRealTime() << " s\n"; - std::cout << "\ttimer_copy_into_w: " << timer_copy_into_w.getRealTime() << " s\n"; - std::cout << "\ttimer_k_loop: " << timer_k_loop.getRealTime() << " s\n"; - std::cout << "\ttimer_dropping: " << timer_dropping.getRealTime() << " s\n"; - std::cout << "\ttimer_copy_into_LU: " << timer_copy_into_LU.getRealTime() << " s\n"; - std::cout << std::flush; +// timer_total.stop(); + +// std::cout << "ILUT::update statistics:\n"; +// std::cout << "\ttimer_total: " << timer_total.getRealTime() << " s\n"; +// std::cout << "\ttimer_rowlengths: " << timer_rowlengths.getRealTime() << " s\n"; +// std::cout << "\ttimer_copy_into_w: " << timer_copy_into_w.getRealTime() << " s\n"; +// std::cout << "\ttimer_k_loop: " << timer_k_loop.getRealTime() << " s\n"; +// std::cout << "\ttimer_heap_construct: " << timer_heap_construct.getRealTime() << " s\n"; +// std::cout << "\ttimer_heap_extract: " << timer_heap_extract.getRealTime() << " s\n"; +// std::cout << "\ttimer_copy_into_LU: " << timer_copy_into_LU.getRealTime() << " s\n"; +// std::cout << "\ttimer_reset: " << timer_reset.getRealTime() << " s\n"; +// std::cout << std::flush; } template< typename Matrix, typename Real, typename Index > -bool +void ILUT_impl< Matrix, Real, Devices::Host, Index >:: -solve( ConstVectorViewType b, VectorViewType x ) const +solve( ConstVectorViewType _b, VectorViewType _x ) const { - TNL_ASSERT_EQ( b.getSize(), L.getRows(), "wrong size of the right hand side" ); - TNL_ASSERT_EQ( x.getSize(), L.getRows(), "wrong size of the solution vector" ); - - const IndexType N = x.getSize(); + const auto b = Traits< Matrix >::getLocalVectorView( _b ); + auto x = Traits< Matrix >::getLocalVectorView( _x ); // Step 1: solve y from Ly = b - for( IndexType i = 0; i < N; i++ ) { - x[ i ] = b[ i ]; - - const auto L_entries = L.getRowLength( i ); - - // this condition is to avoid segfaults on empty L.getRow( i ) - if( L_entries > 0 ) { - const auto L_i = L.getRow( i ); - - // loop for j = 0, ..., i - 1; but only over the non-zero entries - for( IndexType c_j = 0; c_j < L_entries; c_j++ ) { - const auto j = L_i.getElementColumn( c_j ); - // we might have allocated more space than was actually needed due to dropping - if( j >= N ) break; - x[ i ] -= L_i.getElementValue( c_j ) * x[ j ]; - } - } - } + triangularSolveLower< false >( L, x, b ); // Step 2: solve x from Ux = y - for( IndexType i = N - 1; i >= 0; i-- ) { - const IndexType U_idx = N - 1 - i; - - const auto U_entries = U.getRowLength( U_idx ); - const auto U_i = U.getRow( U_idx ); - - const auto U_ii = U_i.getElementValue( 0 ); - - // loop for j = i+1, ..., N-1; but only over the non-zero entries - for( IndexType c_j = 1; c_j < U_entries ; c_j++ ) { - const auto j = U_i.getElementColumn( c_j ); - // we might have allocated more space than was actually needed due to dropping - if( j >= N ) break; - x[ i ] -= U_i.getElementValue( c_j ) * x[ j ]; - } - - x[ i ] /= U_ii; - } - - return true; + triangularSolveUpper< true, false >( U, x, x ); } } // namespace Preconditioners diff --git a/src/TNL/Solvers/Linear/Preconditioners/Preconditioner.h b/src/TNL/Solvers/Linear/Preconditioners/Preconditioner.h index cda81802d..2efc01001 100644 --- a/src/TNL/Solvers/Linear/Preconditioners/Preconditioner.h +++ b/src/TNL/Solvers/Linear/Preconditioners/Preconditioner.h @@ -16,6 +16,8 @@ #include #include +#include "../Traits.h" + namespace TNL { namespace Solvers { namespace Linear { @@ -28,8 +30,8 @@ public: using RealType = typename Matrix::RealType; using DeviceType = typename Matrix::DeviceType; using IndexType = typename Matrix::IndexType; - using VectorViewType = Containers::VectorView< RealType, DeviceType, IndexType >; - using ConstVectorViewType = Containers::VectorView< typename std::add_const< RealType >::type, DeviceType, IndexType >; + using VectorViewType = typename Traits< Matrix >::VectorViewType; + using ConstVectorViewType = typename Traits< Matrix >::ConstVectorViewType; using MatrixType = Matrix; using MatrixPointer = Pointers::SharedPointer< typename std::add_const< MatrixType >::type >; @@ -46,10 +48,9 @@ public: virtual void update( const MatrixPointer& matrixPointer ) {} - virtual bool solve( ConstVectorViewType b, VectorViewType x ) const + virtual void solve( ConstVectorViewType b, VectorViewType x ) const { TNL_ASSERT_TRUE( false, "The solve() method of a dummy preconditioner should not be called." ); - return true; } String getType() const diff --git a/src/TNL/Solvers/Linear/Preconditioners/TriangularSolve.h b/src/TNL/Solvers/Linear/Preconditioners/TriangularSolve.h new file mode 100644 index 000000000..71f51a6eb --- /dev/null +++ b/src/TNL/Solvers/Linear/Preconditioners/TriangularSolve.h @@ -0,0 +1,117 @@ +/*************************************************************************** + TriangularSolve.h - description + ------------------- + begin : Sep 21, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by: Jakub Klinkovsky + +#pragma once + +namespace TNL { +namespace Solvers { +namespace Linear { +namespace Preconditioners { + +/* + * Solves `x` from `Lx = b`, where L is a square lower triangular matrix with + * implicit ones on the diagonal. + * + * Note that the solution can be updated in-place if `x` and `b` are passed + * as the same vector. + * + * If `fullStorage` is true, then it is assumed that all non-zero entries of the + * matrix are valid. Otherwise an explicit check is performed to detect padding + * zeros. This is useful for Ellpack-based formats or if more space than + * necessary was explicitly allocated. + */ +template< bool fullStorage = true, typename Matrix, typename Vector1, typename Vector2 > +void triangularSolveLower( const Matrix& L, Vector1& x, const Vector2& b ) +{ + TNL_ASSERT_EQ( b.getSize(), L.getRows(), "wrong size of the right hand side" ); + TNL_ASSERT_EQ( x.getSize(), L.getRows(), "wrong size of the solution vector" ); + + using RealType = typename Vector1::RealType; + using IndexType = typename Vector1::IndexType; + + const IndexType N = x.getSize(); + + for( IndexType i = 0; i < N; i++ ) { + RealType x_i = b[ i ]; + + const auto L_entries = L.getRowLength( i ); + + // this condition is to avoid segfaults on empty L.getRow( i ) + if( L_entries > 0 ) { + const auto L_i = L.getRow( i ); + + // loop for j = 0, ..., i - 1; but only over the non-zero entries + for( IndexType c_j = 0; c_j < L_entries; c_j++ ) { + const auto j = L_i.getElementColumn( c_j ); + // skip padding zeros + if( fullStorage == false && j >= N ) + break; + x_i -= L_i.getElementValue( c_j ) * x[ j ]; + } + } + + x[ i ] = x_i; + } +} + +/* + * Solves `x` from `Ux = b`, where U is a square upper triangular matrix. + * + * Note that the solution can be updated in-place if `x` and `b` are passed + * as the same vector. + * + * If `reversedRows` is true, the rows of `U` are indexed in reverse order. + * + * If `fullStorage` is true, then it is assumed that all non-zero entries of the + * matrix are valid. Otherwise an explicit check is performed to detect padding + * zeros. This is useful for Ellpack-based formats or if more space than + * necessary was explicitly allocated. + */ +template< bool reversedRows = false, bool fullStorage = true, + typename Matrix, typename Vector1, typename Vector2 > +void triangularSolveUpper( const Matrix& U, Vector1& x, const Vector2& b ) +{ + TNL_ASSERT_EQ( b.getSize(), U.getRows(), "wrong size of the right hand side" ); + TNL_ASSERT_EQ( x.getSize(), U.getRows(), "wrong size of the solution vector" ); + + using RealType = typename Vector1::RealType; + using IndexType = typename Vector1::IndexType; + + const IndexType N = x.getSize(); + + for( IndexType i = N - 1; i >= 0; i-- ) { + RealType x_i = b[ i ]; + + const IndexType U_idx = (reversedRows) ? N - 1 - i : i; + + const auto U_entries = U.getRowLength( U_idx ); + const auto U_i = U.getRow( U_idx ); + + const auto U_ii = U_i.getElementValue( 0 ); + + // loop for j = i+1, ..., N-1; but only over the non-zero entries + for( IndexType c_j = 1; c_j < U_entries ; c_j++ ) { + const auto j = U_i.getElementColumn( c_j ); + // skip padding zeros + if( fullStorage == false && j >= N ) + break; + x_i -= U_i.getElementValue( c_j ) * x[ j ]; + } + + x[ i ] = x_i / U_ii; + } +} + +} // namespace Preconditioners +} // namespace Linear +} // namespace Solvers +} // namespace TNL diff --git a/src/TNL/Solvers/Linear/TFQMR.h b/src/TNL/Solvers/Linear/TFQMR.h index e693032a3..73d0894aa 100644 --- a/src/TNL/Solvers/Linear/TFQMR.h +++ b/src/TNL/Solvers/Linear/TFQMR.h @@ -12,8 +12,6 @@ #include "LinearSolver.h" -#include - namespace TNL { namespace Solvers { namespace Linear { @@ -35,11 +33,9 @@ public: bool solve( ConstVectorViewType b, VectorViewType x ) override; protected: - void setSize( IndexType size ); - - Containers::Vector< RealType, DeviceType, IndexType > d, r, w, u, v, r_ast, Au, M_tmp; + void setSize( const VectorViewType& x ); - IndexType size = 0; + typename Traits< Matrix >::VectorType d, r, w, u, v, r_ast, Au, M_tmp; }; } // namespace Linear diff --git a/src/TNL/Solvers/Linear/TFQMR_impl.h b/src/TNL/Solvers/Linear/TFQMR_impl.h index f87d96152..3f144875d 100644 --- a/src/TNL/Solvers/Linear/TFQMR_impl.h +++ b/src/TNL/Solvers/Linear/TFQMR_impl.h @@ -29,7 +29,7 @@ String TFQMR< Matrix > :: getType() const template< typename Matrix > bool TFQMR< Matrix >::solve( ConstVectorViewType b, VectorViewType x ) { - this->setSize( this->matrix->getRows() ); + this->setSize( x ); RealType tau, theta, eta, rho, alpha, b_norm, w_norm; @@ -129,19 +129,16 @@ bool TFQMR< Matrix >::solve( ConstVectorViewType b, VectorViewType x ) } template< typename Matrix > -void TFQMR< Matrix > :: setSize( IndexType size ) +void TFQMR< Matrix > :: setSize( const VectorViewType& x ) { - if( this->size == size ) - return; - this->size = size; - d.setSize( size ); - r.setSize( size ); - w.setSize( size ); - u.setSize( size ); - v.setSize( size ); - r_ast.setSize( size ); - Au.setSize( size ); - M_tmp.setSize( size ); + d.setLike( x ); + r.setLike( x ); + w.setLike( x ); + u.setLike( x ); + v.setLike( x ); + r_ast.setLike( x ); + Au.setLike( x ); + M_tmp.setLike( x ); } } // namespace Linear diff --git a/src/TNL/Solvers/Linear/Traits.h b/src/TNL/Solvers/Linear/Traits.h new file mode 100644 index 000000000..5fd61c015 --- /dev/null +++ b/src/TNL/Solvers/Linear/Traits.h @@ -0,0 +1,102 @@ +/*************************************************************************** + Traits.h - description + ------------------- + begin : Sep 20, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by: Jakub Klinkovský + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace TNL { +namespace Solvers { +namespace Linear { + +template< typename Matrix > +struct Traits +{ + using CommunicatorType = Communicators::NoDistrCommunicator; + + using VectorType = Containers::Vector + < typename Matrix::RealType, + typename Matrix::DeviceType, + typename Matrix::IndexType >; + using VectorViewType = Containers::VectorView + < typename Matrix::RealType, + typename Matrix::DeviceType, + typename Matrix::IndexType >; + using ConstVectorViewType = Containers::VectorView + < typename std::add_const< typename Matrix::RealType >::type, + typename Matrix::DeviceType, + typename Matrix::IndexType >; + + // compatibility aliases + using LocalVectorType = VectorType; + using LocalVectorViewType = VectorViewType; + using ConstLocalVectorViewType = ConstVectorViewType; + + // compatibility wrappers for some DistributedMatrix methods + static const Matrix& getLocalMatrix( const Matrix& m ) { return m; } + static ConstLocalVectorViewType getLocalVectorView( ConstVectorViewType v ) { return v; } + static LocalVectorViewType getLocalVectorView( VectorViewType v ) { return v; } + + static typename CommunicatorType::CommunicationGroup getCommunicationGroup( const Matrix& m ) { return CommunicatorType::AllGroup; } +}; + +template< typename Matrix, typename Communicator > +struct Traits< DistributedContainers::DistributedMatrix< Matrix, Communicator > > +{ + using CommunicatorType = Communicator; + + using VectorType = DistributedContainers::DistributedVector + < typename Matrix::RealType, + typename Matrix::DeviceType, + typename Matrix::IndexType, + Communicator >; + using VectorViewType = DistributedContainers::DistributedVectorView + < typename Matrix::RealType, + typename Matrix::DeviceType, + typename Matrix::IndexType, + Communicator >; + using ConstVectorViewType = DistributedContainers::DistributedVectorView + < typename std::add_const< typename Matrix::RealType >::type, + typename Matrix::DeviceType, + typename Matrix::IndexType, + Communicator >; + + using LocalVectorType = Containers::Vector + < typename Matrix::RealType, + typename Matrix::DeviceType, + typename Matrix::IndexType >; + using LocalVectorViewType = Containers::VectorView + < typename Matrix::RealType, + typename Matrix::DeviceType, + typename Matrix::IndexType >; + using ConstLocalVectorViewType = Containers::VectorView + < typename std::add_const< typename Matrix::RealType >::type, + typename Matrix::DeviceType, + typename Matrix::IndexType >; + + // compatibility wrappers for some DistributedMatrix methods + static const Matrix& getLocalMatrix( const DistributedContainers::DistributedMatrix< Matrix, Communicator >& m ) + { return m.getLocalMatrix(); } + static ConstLocalVectorViewType getLocalVectorView( ConstVectorViewType v ) { return v.getLocalVectorView(); } + static LocalVectorViewType getLocalVectorView( VectorViewType v ) { return v.getLocalVectorView(); } + + static typename CommunicatorType::CommunicationGroup getCommunicationGroup( const DistributedContainers::DistributedMatrix< Matrix, Communicator >& m ) { return m.getCommunicationGroup(); } +}; + +} // namespace Linear +} // namespace Solvers +} // namespace TNL diff --git a/src/TNL/Solvers/LinearSolverTypeResolver.h b/src/TNL/Solvers/LinearSolverTypeResolver.h index 884203800..61a141f50 100644 --- a/src/TNL/Solvers/LinearSolverTypeResolver.h +++ b/src/TNL/Solvers/LinearSolverTypeResolver.h @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -45,8 +44,6 @@ getLinearSolver( const Config::ParameterContainer& parameters ) return std::make_shared< Linear::BICGStabL< MatrixType > >(); if( discreteSolver == "gmres" ) return std::make_shared< Linear::GMRES< MatrixType > >(); - if( discreteSolver == "cwygmres" ) - return std::make_shared< Linear::CWYGMRES< MatrixType > >(); if( discreteSolver == "tfqmr" ) return std::make_shared< Linear::TFQMR< MatrixType > >(); #ifdef HAVE_UMFPACK @@ -54,7 +51,7 @@ getLinearSolver( const Config::ParameterContainer& parameters ) return std::make_shared< Linear::UmfpackWrapper< MatrixType > >(); #endif - std::cerr << "Unknown semi-implicit discrete solver " << discreteSolver << ". It can be only: sor, cg, bicgstab, bicgstabl, gmres, cwygmres, tfqmr"; + std::cerr << "Unknown semi-implicit discrete solver " << discreteSolver << ". It can be only: sor, cg, bicgstab, bicgstabl, gmres, tfqmr"; #ifdef HAVE_UMFPACK std::cerr << ", umfpack" #endif diff --git a/src/TNL/Solvers/SolverConfig_impl.h b/src/TNL/Solvers/SolverConfig_impl.h index bc86767e1..598cee285 100644 --- a/src/TNL/Solvers/SolverConfig_impl.h +++ b/src/TNL/Solvers/SolverConfig_impl.h @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -135,7 +134,6 @@ bool SolverConfig< ConfigTag, ProblemConfig >::configSetup( Config::ConfigDescri config.addEntryEnum( "cg" ); config.addEntryEnum( "bicgstab" ); config.addEntryEnum( "bicgstabl" ); - config.addEntryEnum( "cwygmres" ); config.addEntryEnum( "gmres" ); config.addEntryEnum( "tfqmr" ); config.addEntryEnum( "sor" ); @@ -174,10 +172,7 @@ bool SolverConfig< ConfigTag, ProblemConfig >::configSetup( Config::ConfigDescri Linear::CG< MatrixType >::configSetup( config ); Linear::BICGStab< MatrixType >::configSetup( config ); Linear::BICGStabL< MatrixType >::configSetup( config ); - - // GMRES and CWYGMRES have the same options Linear::GMRES< MatrixType >::configSetup( config ); - Linear::TFQMR< MatrixType >::configSetup( config ); Linear::SOR< MatrixType >::configSetup( config ); diff --git a/src/TNL/String.h b/src/TNL/String.h index 36c9f7e2d..6e8ab7192 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -26,20 +26,21 @@ template< typename T > String convertToString( const T& value ); ///// -// \brief Class for managing strings +// \brief Class for managing strings. class String { public: ///// - /// \brief Basic constructor + /// \brief Basic constructor. Constructs an empty string object, with the length of zero characters. String(); ///// /// \brief Constructor with char pointer. - /// Constructor with char pointer. - /// @param prefix_cut_off says length of the prefix that is going to be omitted and - /// @param sufix_cut_off says the same about suffix. + /// Copies the null-terminated character sequence (C-string) pointed by \e c. + /// Constructs a string initialized with the 8-bit string \e c, excluding the given number of \e prefix_cut_off and \e sufix_cut_off characters. + /// @param prefix_cut_off determines the length of the prefix that is going to be omitted from the string \e c + /// @param sufix_cut_off determines the length of the sufix that is going to be omitted from the string \e c String( const char* c, int prefix_cut_off = 0, int sufix_cut_off = 0 ); @@ -48,13 +49,14 @@ class String int prefix_cut_off = 0, int sufix_cut_off = 0 ); - + /// Returns type of string - String. static String getType(); - //! Copy constructor + ///// + /// \brief Copy constructor. Constructs a copy of the string \e str. String( const String& str ); - //! Convert anything to a string + /// \brief Converts anything to a string. template< typename T > String( T value ) : string( nullptr ), length( 0 ) @@ -62,107 +64,131 @@ class String setString( convertToString( value ).getString() ); } - //! Destructor + /// \brief Destructor. ~String(); - //! Return length of the string + /// Returns the number of characters in given string. Equivalent to \c getSize(). int getLength() const; + /// Returns the number of characters in given string. int getSize() const; - //! Return currently allocated size + /// Returns size of allocated storage for given string. int getAllocatedSize() const; - //! Reserve space for given number of characters + /// Reserves space for given number of characters (\e size). + /// Requests to allocate storage for given \e size (number of characters). void setSize( int size ); - //! Set string from given char pointer - /*! @param prefix_cut_off says length of the prefix that is going to be omitted and - @param sufix_cut_off says the same about sufix. - */ + ///// + /// Sets string from given char pointer \e c. + /// @param prefix_cut_off determines the length of the prefix that is going to be omitted from the string \e c + /// @param sufix_cut_off determines the length of the sufix that is going to be omitted from the string \e c void setString( const char* c, int prefix_cut_off = 0, int sufix_cut_off = 0 ); - //! Return pointer to data + /// Returns pointer to data. It returns the content of the given string. const char* getString() const; - //! Return pointer to data + /// Returns pointer to data. char* getString(); - //! Operator for accesing particular chars of the string + /// \brief Operator for accesing particular chars of the string. This function overloads operator[](). It returns a reference to the character at position \e i in given string. const char& operator[]( int i ) const; - //! Operator for accesing particular chars of the string + /// \brief Operator for accesing particular chars of the string. It returns the character at the position \e i in given string as a modifiable reference. char& operator[]( int i ); - /**** - * Operators for C strings - */ + ///// + /// \brief Operators for C strings. + /// This function overloads operator=(). It assigns \e str to this string, replacing its current contents. String& operator=( const char* str ); + /// This function overloads operator+=(). It appends the string \e str to this string. String& operator+=( const char* str ); + /// This function concatenates strings and returns a newly constructed string object. String operator+( const char* str ) const; + /// This function overloads operator==(). bool operator==( const char* str ) const; + /// This function overloads operator!=(). bool operator!=( const char* str ) const; - /**** - * Operators for Strings - */ + ///// + /// \brief Operators for Strings. + /// This function assigns \e str to this string and returns a reference to this string. String& operator=( const String& str ); + /// This function appends the string \e str onto the end of this string and returns a reference to this string. String& operator+=( const String& str ); + /// This function concatenates strings and returns a newly constructed string object. String operator+( const String& str ) const; + /// This function overloads operator==(). It returns \c true if this string is equal to \e str, otherwise returns \c false. bool operator==( const String& str ) const; + /// This function overloads operator!=(). It returns \c true if this string is not equal to \e str, otherwise returns \c false. bool operator!=( const String& str ) const; - /**** - * Operators for single characters - */ + ///// + /// \brief Operators for single characters. + /// This function overloads operator=(). It assigns character /e str to this string. String& operator=( char str ); + /// This function overloads operator+=(). It appends character /e str to this string. String& operator+=( char str ); + // This function concatenates strings and returns a newly constructed string object. String operator+( char str ) const; + // This function concatenates strings and returns a newly constructed string object. bool operator==( char str ) const; + /// This function overloads operator!=(). bool operator!=( char str ) const; - //! Cast to bool operator + /// \brief Cast to bool operator. operator bool() const; - //! Cast to bool with negation operator + /// \brief Cast to bool with negation operator. bool operator!() const; + ///// + /// \brief Replaces portion of string. + ///It replaces section \e pattern from this string with new piece of string \e replaceWith. + ///If parameter \e count is defined, the function makes replacement several times, every time when it finds the same pattern in this string. String replace( const String& pattern, const String& replaceWith, int count = 0 ) const; + /// \brief Trims/strips given string. It removes all spaces from string except for single spaces between words. String strip( char strip = ' ' ) const; - //! Split the string into list of strings w.r.t. given separator. + /// \brief Splits string into list of strings with respect to given \e separator. + /// It splits the string into list of substrings wherever \e separator occurs, and returs list of those strings. + /// When \e separator does not appear anywhere in the given string, this function returns a single-element list containing given sting. + /// @param separator Character, which separates substrings in given string. Empty character can not be used. int split( Containers::List< String >& list, const char separator = ' ' ) const; - //! Write to a binary file + /// Write to a binary file bool save( File& file ) const; - //! Read from binary file + /// Read from binary file bool load( File& file ); //! Broadcast to other nodes in MPI cluster - // void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); + // void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); - //! Read one line from given stream. + /// Read one line from given stream. bool getLine( std::istream& stream ); friend std::ostream& operator<<( std::ostream& stream, const String& str ); protected: - //! Pointer to char ended with zero + /// Pointer to char ended with zero char* string; - //! Length of the allocated piece of memory + /// Length of the allocated piece of memory int length; }; +/// Returns concatenation of \e string1 and \e string2. String operator+( char string1, const String& string2 ); +/// Returns concatenation of \e string1 and \e string2. String operator+( const char* string1, const String& string2 ); std::ostream& operator<<( std::ostream& stream, const String& str ); diff --git a/src/UnitTests/CMakeLists.txt b/src/UnitTests/CMakeLists.txt index e7132a722..cf0fc8c47 100644 --- a/src/UnitTests/CMakeLists.txt +++ b/src/UnitTests/CMakeLists.txt @@ -1,4 +1,5 @@ ADD_SUBDIRECTORY( Containers ) +ADD_SUBDIRECTORY( DistributedContainers ) ADD_SUBDIRECTORY( Functions ) ADD_SUBDIRECTORY( Matrices ) ADD_SUBDIRECTORY( Meshes ) @@ -30,17 +31,17 @@ else() tnl ) endif() +ADD_EXECUTABLE( FileNameTest FileNameTest.cpp ) +TARGET_COMPILE_OPTIONS( FileNameTest PRIVATE ${CXX_TESTS_FLAGS} ) +TARGET_LINK_LIBRARIES( FileNameTest ${GTEST_BOTH_LIBRARIES} tnl ) + ADD_EXECUTABLE( StringTest StringTest.cpp ) TARGET_COMPILE_OPTIONS( StringTest PRIVATE ${CXX_TESTS_FLAGS} ) -TARGET_LINK_LIBRARIES( StringTest - ${GTEST_BOTH_LIBRARIES} - tnl ) +TARGET_LINK_LIBRARIES( StringTest ${GTEST_BOTH_LIBRARIES} tnl ) ADD_EXECUTABLE( ObjectTest ObjectTest.cpp ) TARGET_COMPILE_OPTIONS( ObjectTest PRIVATE ${CXX_TESTS_FLAGS} ) -TARGET_LINK_LIBRARIES( ObjectTest - ${GTEST_BOTH_LIBRARIES} - tnl ) +TARGET_LINK_LIBRARIES( ObjectTest ${GTEST_BOTH_LIBRARIES} tnl ) ADD_EXECUTABLE( SaveAndLoadMeshfunctionTest SaveAndLoadMeshfunctionTest.cpp ) TARGET_COMPILE_OPTIONS( SaveAndLoadMeshfunctionTest PRIVATE ${CXX_TESTS_FLAGS} ) diff --git a/src/UnitTests/Containers/CMakeLists.txt b/src/UnitTests/Containers/CMakeLists.txt index 3fc375581..dbde4568f 100644 --- a/src/UnitTests/Containers/CMakeLists.txt +++ b/src/UnitTests/Containers/CMakeLists.txt @@ -66,6 +66,20 @@ ELSE( BUILD_CUDA ) tnl ) ENDIF( BUILD_CUDA ) +IF( BUILD_CUDA ) + CUDA_ADD_EXECUTABLE( MultireductionTest MultireductionTest.cu + OPTIONS ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( MultireductionTest + ${GTEST_BOTH_LIBRARIES} + tnl ) +ELSE( BUILD_CUDA ) + ADD_EXECUTABLE( MultireductionTest MultireductionTest.cpp ) + TARGET_COMPILE_OPTIONS( MultireductionTest PRIVATE ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( MultireductionTest + ${GTEST_BOTH_LIBRARIES} + tnl ) +ENDIF( BUILD_CUDA ) + ADD_EXECUTABLE( StaticVectorTest StaticVectorTest.cpp ) TARGET_COMPILE_OPTIONS( StaticVectorTest PRIVATE ${CXX_TESTS_FLAGS} ) TARGET_LINK_LIBRARIES( StaticVectorTest @@ -93,6 +107,7 @@ ADD_TEST( ArrayTest ${EXECUTABLE_OUTPUT_PATH}/ArrayTest${CMAKE_EXECUTABLE_SUFFIX ADD_TEST( ArrayViewTest ${EXECUTABLE_OUTPUT_PATH}/ArrayViewTest${CMAKE_EXECUTABLE_SUFFIX} ) ADD_TEST( StaticArrayTest ${EXECUTABLE_OUTPUT_PATH}/StaticArrayTest${CMAKE_EXECUTABLE_SUFFIX} ) ADD_TEST( VectorTest ${EXECUTABLE_OUTPUT_PATH}/VectorTest${CMAKE_EXECUTABLE_SUFFIX} ) +ADD_TEST( MultireductionTest ${EXECUTABLE_OUTPUT_PATH}/MultireductionTest${CMAKE_EXECUTABLE_SUFFIX} ) ADD_TEST( StaticVectorTest ${EXECUTABLE_OUTPUT_PATH}/StaticVectorTest${CMAKE_EXECUTABLE_SUFFIX} ) #ADD_TEST( MultiArrayTest ${EXECUTABLE_OUTPUT_PATH}/MultiArrayTest${CMAKE_EXECUTABLE_SUFFIX} ) diff --git a/src/UnitTests/Containers/MultireductionTest.cpp b/src/UnitTests/Containers/MultireductionTest.cpp new file mode 100644 index 000000000..c36965c92 --- /dev/null +++ b/src/UnitTests/Containers/MultireductionTest.cpp @@ -0,0 +1 @@ +#include "MultireductionTest.h" diff --git a/src/UnitTests/Containers/MultireductionTest.cu b/src/UnitTests/Containers/MultireductionTest.cu new file mode 100644 index 000000000..c36965c92 --- /dev/null +++ b/src/UnitTests/Containers/MultireductionTest.cu @@ -0,0 +1 @@ +#include "MultireductionTest.h" diff --git a/src/UnitTests/Containers/MultireductionTest.h b/src/UnitTests/Containers/MultireductionTest.h new file mode 100644 index 000000000..7f3c26fc4 --- /dev/null +++ b/src/UnitTests/Containers/MultireductionTest.h @@ -0,0 +1,132 @@ +/*************************************************************************** + MultireductionTest.h - description + ------------------- + begin : Oct 1, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#ifdef HAVE_GTEST +#include "gtest/gtest.h" + +#include +#include +#include + +using namespace TNL; +using namespace TNL::Containers; +using namespace TNL::Containers::Algorithms; + +template< typename View > +void setLinearSequence( View& deviceVector ) +{ + using HostVector = Containers::Vector< typename View::RealType, Devices::Host, typename View::IndexType >; + HostVector a; + a.setLike( deviceVector ); + for( int i = 0; i < a.getSize(); i++ ) + a[ i ] = i; + deviceVector = a; +} + +template< typename View > +void setNegativeLinearSequence( View& deviceVector ) +{ + using HostVector = Containers::Vector< typename View::RealType, Devices::Host, typename View::IndexType >; + HostVector a; + a.setLike( deviceVector ); + for( int i = 0; i < a.getSize(); i++ ) + a[ i ] = -i; + deviceVector = a; +} + +// test fixture for typed tests +template< typename Vector > +class MultireductionTest : public ::testing::Test +{ +protected: + using DeviceVector = Vector; + using DeviceView = VectorView< typename Vector::RealType, typename Vector::DeviceType, typename Vector::IndexType >; + using HostVector = typename DeviceVector::HostType; + using HostView = typename DeviceView::HostType; + + // should be small enough to have fast tests, but larger than minGPUReductionDataSize + // and large enough to require multiple CUDA blocks for reduction + static constexpr int size = 5000; + + // number of vectors which are reduced together + static constexpr int n = 4; + + DeviceVector V; + DeviceVector y; + HostVector result; + + MultireductionTest() + { + V.setSize( size * n ); + y.setSize( size ); + result.setSize( n ); + + for( int i = 0; i < n; i++ ) { + DeviceView v( &V[ i * size ], size ); + if( i % 2 == 0 ) + setLinearSequence( v ); + else + setNegativeLinearSequence( v ); + } + y.setValue( 1 ); + } +}; + +// types for which MultireductionTest is instantiated +using VectorTypes = ::testing::Types< + Vector< int, Devices::Host >, + Vector< float, Devices::Host > +#ifdef HAVE_CUDA + , + Vector< int, Devices::Cuda >, + Vector< float, Devices::Cuda > +#endif +>; + +TYPED_TEST_CASE( MultireductionTest, VectorTypes ); + +TYPED_TEST( MultireductionTest, scalarProduct ) +{ + using RealType = typename TestFixture::DeviceVector::RealType; + using DeviceType = typename TestFixture::DeviceVector::DeviceType; + + ParallelReductionScalarProduct< RealType, RealType > scalarProduct; + Multireduction< DeviceType >::reduce + ( scalarProduct, + this->n, + this->size, + this->V.getData(), + this->size, + this->y.getData(), + this->result.getData() ); + + for( int i = 0; i < this->n; i++ ) { + if( i % 2 == 0 ) + EXPECT_EQ( this->result[ i ], 0.5 * this->size * ( this->size - 1 ) ); + else + EXPECT_EQ( this->result[ i ], - 0.5 * this->size * ( this->size - 1 ) ); + } +} + +#endif // HAVE_GTEST + + +#include "../GtestMissingError.h" +int main( int argc, char* argv[] ) +{ +#ifdef HAVE_GTEST + ::testing::InitGoogleTest( &argc, argv ); + return RUN_ALL_TESTS(); +#else + throw GtestMissingError(); +#endif +} diff --git a/src/UnitTests/Containers/VectorTest.h b/src/UnitTests/Containers/VectorTest.h index 47d390892..5683ff17e 100644 --- a/src/UnitTests/Containers/VectorTest.h +++ b/src/UnitTests/Containers/VectorTest.h @@ -23,8 +23,8 @@ using namespace TNL; using namespace TNL::Containers; -using namespace TNL::Arithmetics; using namespace TNL::Containers::Algorithms; +using namespace TNL::Arithmetics; // should be small enough to have fast tests, but larger than minGPUReductionDataSize // and large enough to require multiple CUDA blocks for reduction diff --git a/src/UnitTests/DistributedContainers/CMakeLists.txt b/src/UnitTests/DistributedContainers/CMakeLists.txt new file mode 100644 index 000000000..cd1ac71d8 --- /dev/null +++ b/src/UnitTests/DistributedContainers/CMakeLists.txt @@ -0,0 +1,50 @@ +if( ${BUILD_MPI} ) + +if( BUILD_CUDA ) + CUDA_ADD_EXECUTABLE( DistributedArrayTest DistributedArrayTest.cu + OPTIONS ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( DistributedArrayTest + ${GTEST_BOTH_LIBRARIES} + tnl ) + + CUDA_ADD_EXECUTABLE( DistributedVectorTest DistributedVectorTest.cu + OPTIONS ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( DistributedVectorTest + ${GTEST_BOTH_LIBRARIES} + tnl ) + + CUDA_ADD_EXECUTABLE( DistributedMatrixTest DistributedMatrixTest.cu + OPTIONS ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( DistributedMatrixTest + ${GTEST_BOTH_LIBRARIES} + tnl ) +else() + ADD_EXECUTABLE( DistributedArrayTest DistributedArrayTest.cpp ) + TARGET_COMPILE_OPTIONS( DistributedArrayTest PRIVATE ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( DistributedArrayTest + ${GTEST_BOTH_LIBRARIES} + tnl ) + + ADD_EXECUTABLE( DistributedVectorTest DistributedVectorTest.cpp ) + TARGET_COMPILE_OPTIONS( DistributedVectorTest PRIVATE ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( DistributedVectorTest + ${GTEST_BOTH_LIBRARIES} + tnl ) + + ADD_EXECUTABLE( DistributedMatrixTest DistributedMatrixTest.cpp ) + TARGET_COMPILE_OPTIONS( DistributedMatrixTest PRIVATE ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( DistributedMatrixTest + ${GTEST_BOTH_LIBRARIES} + tnl ) +endif() + +SET( mpi_test_parameters -np 4 -H localhost:4 "${EXECUTABLE_OUTPUT_PATH}/DistributedArrayTest${CMAKE_EXECUTABLE_SUFFIX}" ) +ADD_TEST( NAME DistributedArrayTest COMMAND "mpirun" ${mpi_test_parameters}) + +SET( mpi_test_parameters -np 4 -H localhost:4 "${EXECUTABLE_OUTPUT_PATH}/DistributedVectorTest${CMAKE_EXECUTABLE_SUFFIX}" ) +ADD_TEST( NAME DistributedVectorTest COMMAND "mpirun" ${mpi_test_parameters}) + +SET( mpi_test_parameters -np 4 -H localhost:4 "${EXECUTABLE_OUTPUT_PATH}/DistributedMatrixTest${CMAKE_EXECUTABLE_SUFFIX}" ) +ADD_TEST( NAME DistributedMatrixTest COMMAND "mpirun" ${mpi_test_parameters}) + +endif() diff --git a/src/UnitTests/DistributedContainers/DistributedArrayTest.cpp b/src/UnitTests/DistributedContainers/DistributedArrayTest.cpp new file mode 100644 index 000000000..051716e16 --- /dev/null +++ b/src/UnitTests/DistributedContainers/DistributedArrayTest.cpp @@ -0,0 +1 @@ +#include "DistributedArrayTest.h" diff --git a/src/UnitTests/DistributedContainers/DistributedArrayTest.cu b/src/UnitTests/DistributedContainers/DistributedArrayTest.cu new file mode 100644 index 000000000..051716e16 --- /dev/null +++ b/src/UnitTests/DistributedContainers/DistributedArrayTest.cu @@ -0,0 +1 @@ +#include "DistributedArrayTest.h" diff --git a/src/UnitTests/DistributedContainers/DistributedArrayTest.h b/src/UnitTests/DistributedContainers/DistributedArrayTest.h new file mode 100644 index 000000000..4a5b4007b --- /dev/null +++ b/src/UnitTests/DistributedContainers/DistributedArrayTest.h @@ -0,0 +1,346 @@ +/*************************************************************************** + DistributedArrayTest.h - description + ------------------- + begin : Sep 6, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +#ifdef HAVE_GTEST +#include + +#include +#include +#include +#include +#include + +using namespace TNL; +using namespace TNL::DistributedContainers; + +/* + * Light check of DistributedArray. + * + * - Number of processes is not limited. + * - Global size is hardcoded as 97 to force non-uniform distribution. + * - Communication group is hardcoded as AllGroup -- it may be changed as needed. + */ +template< typename DistributedArray > +class DistributedArrayTest +: public ::testing::Test +{ +protected: + using ValueType = typename DistributedArray::ValueType; + using DeviceType = typename DistributedArray::DeviceType; + using CommunicatorType = typename DistributedArray::CommunicatorType; + using IndexType = typename DistributedArray::IndexType; + using DistributedArrayType = DistributedArray; + using ArrayViewType = typename DistributedArrayType::LocalArrayViewType; + using ArrayType = typename DistributedArrayType::LocalArrayType; + + const int globalSize = 97; // prime number to force non-uniform distribution + + const typename CommunicatorType::CommunicationGroup group = CommunicatorType::AllGroup; + + DistributedArrayType distributedArray; + + const int rank = CommunicatorType::GetRank(group); + const int nproc = CommunicatorType::GetSize(group); + + DistributedArrayTest() + { + using LocalRangeType = typename DistributedArray::LocalRangeType; + const LocalRangeType localRange = DistributedContainers::Partitioner< IndexType, CommunicatorType >::splitRange( globalSize, group ); + distributedArray.setDistribution( localRange, globalSize, group ); + + EXPECT_EQ( distributedArray.getLocalRange(), localRange ); + EXPECT_EQ( distributedArray.getCommunicationGroup(), group ); + } +}; + +// types for which DistributedArrayTest is instantiated +using DistributedArrayTypes = ::testing::Types< + DistributedArray< double, Devices::Host, int, Communicators::MpiCommunicator >, + DistributedArray< double, Devices::Host, int, Communicators::NoDistrCommunicator > +#ifdef HAVE_CUDA + , + DistributedArray< double, Devices::Cuda, int, Communicators::MpiCommunicator >, + DistributedArray< double, Devices::Cuda, int, Communicators::NoDistrCommunicator > +#endif +>; + +TYPED_TEST_CASE( DistributedArrayTest, DistributedArrayTypes ); + +TYPED_TEST( DistributedArrayTest, checkSumOfLocalSizes ) +{ + using CommunicatorType = typename TestFixture::CommunicatorType; + + const int localSize = this->distributedArray.getLocalArrayView().getSize(); + int sumOfLocalSizes = 0; + CommunicatorType::Allreduce( &localSize, &sumOfLocalSizes, 1, MPI_SUM, this->group ); + EXPECT_EQ( sumOfLocalSizes, this->globalSize ); + EXPECT_EQ( this->distributedArray.getSize(), this->globalSize ); +} + +TYPED_TEST( DistributedArrayTest, copyFromGlobal ) +{ + using ArrayViewType = typename TestFixture::ArrayViewType; + using ArrayType = typename TestFixture::ArrayType; + + this->distributedArray.setValue( 0.0 ); + ArrayViewType localArrayView = this->distributedArray.getLocalArrayView(); + ArrayType globalArray( this->globalSize ); + globalArray.setValue( 1.0 ); + this->distributedArray.copyFromGlobal( globalArray ); + EXPECT_EQ( localArrayView, globalArray ); +} + +TYPED_TEST( DistributedArrayTest, setLike ) +{ + using DistributedArrayType = typename TestFixture::DistributedArrayType; + + EXPECT_EQ( this->distributedArray.getSize(), this->globalSize ); + DistributedArrayType copy; + EXPECT_EQ( copy.getSize(), 0 ); + copy.setLike( this->distributedArray ); + EXPECT_EQ( copy.getSize(), this->globalSize ); +} + +TYPED_TEST( DistributedArrayTest, reset ) +{ + EXPECT_EQ( this->distributedArray.getSize(), this->globalSize ); + EXPECT_GT( this->distributedArray.getLocalArrayView().getSize(), 0 ); + this->distributedArray.reset(); + EXPECT_EQ( this->distributedArray.getSize(), 0 ); + EXPECT_EQ( this->distributedArray.getLocalArrayView().getSize(), 0 ); +} + +// TODO: swap + +TYPED_TEST( DistributedArrayTest, setValue ) +{ + using ArrayViewType = typename TestFixture::ArrayViewType; + using ArrayType = typename TestFixture::ArrayType; + + this->distributedArray.setValue( 1.0 ); + ArrayViewType localArrayView = this->distributedArray.getLocalArrayView(); + ArrayType expected( localArrayView.getSize() ); + expected.setValue( 1.0 ); + EXPECT_EQ( localArrayView, expected ); +} + +TYPED_TEST( DistributedArrayTest, elementwiseAccess ) +{ + using ArrayViewType = typename TestFixture::ArrayViewType; + using IndexType = typename TestFixture::IndexType; + + this->distributedArray.setValue( 0 ); + ArrayViewType localArrayView = this->distributedArray.getLocalArrayView(); + const auto localRange = this->distributedArray.getLocalRange(); + + // check initial value + for( IndexType i = 0; i < localArrayView.getSize(); i++ ) { + const IndexType gi = localRange.getGlobalIndex( i ); + EXPECT_EQ( localArrayView.getElement( i ), 0 ); + EXPECT_EQ( this->distributedArray.getElement( gi ), 0 ); + if( std::is_same< typename TestFixture::DeviceType, Devices::Host >::value ) + EXPECT_EQ( this->distributedArray[ gi ], 0 ); + } + + // use setValue + for( IndexType i = 0; i < localArrayView.getSize(); i++ ) { + const IndexType gi = localRange.getGlobalIndex( i ); + this->distributedArray.setElement( gi, i + 1 ); + } + + // check set value + for( IndexType i = 0; i < localArrayView.getSize(); i++ ) { + const IndexType gi = localRange.getGlobalIndex( i ); + EXPECT_EQ( localArrayView.getElement( i ), i + 1 ); + EXPECT_EQ( this->distributedArray.getElement( gi ), i + 1 ); + if( std::is_same< typename TestFixture::DeviceType, Devices::Host >::value ) + EXPECT_EQ( this->distributedArray[ gi ], i + 1 ); + } + + this->distributedArray.setValue( 0 ); + + // use operator[] + if( std::is_same< typename TestFixture::DeviceType, Devices::Host >::value ) { + for( IndexType i = 0; i < localArrayView.getSize(); i++ ) { + const IndexType gi = localRange.getGlobalIndex( i ); + this->distributedArray[ gi ] = i + 1; + } + + // check set value + for( IndexType i = 0; i < localArrayView.getSize(); i++ ) { + const IndexType gi = localRange.getGlobalIndex( i ); + EXPECT_EQ( localArrayView.getElement( i ), i + 1 ); + EXPECT_EQ( this->distributedArray.getElement( gi ), i + 1 ); + EXPECT_EQ( this->distributedArray[ gi ], i + 1 ); + } + } +} + +TYPED_TEST( DistributedArrayTest, copyConstructor ) +{ + using DistributedArrayType = typename TestFixture::DistributedArrayType; + + this->distributedArray.setValue( 1 ); + DistributedArrayType copy( this->distributedArray ); + // Array has "binding" copy-constructor + EXPECT_EQ( copy.getLocalArrayView().getData(), this->distributedArray.getLocalArrayView().getData() ); +} + +TYPED_TEST( DistributedArrayTest, copyAssignment ) +{ + using DistributedArrayType = typename TestFixture::DistributedArrayType; + + this->distributedArray.setValue( 1 ); + DistributedArrayType copy; + copy = this->distributedArray; + // no binding, but deep copy + EXPECT_NE( copy.getLocalArrayView().getData(), this->distributedArray.getLocalArrayView().getData() ); + EXPECT_EQ( copy.getLocalArrayView(), this->distributedArray.getLocalArrayView() ); +} + +TYPED_TEST( DistributedArrayTest, comparisonOperators ) +{ + using DistributedArrayType = typename TestFixture::DistributedArrayType; + using IndexType = typename TestFixture::IndexType; + + const auto localRange = this->distributedArray.getLocalRange(); + DistributedArrayType& u = this->distributedArray; + DistributedArrayType v, w; + v.setLike( u ); + w.setLike( u ); + + for( int i = 0; i < u.getLocalArrayView().getSize(); i ++ ) { + const IndexType gi = localRange.getGlobalIndex( i ); + u.setElement( gi, i ); + v.setElement( gi, i ); + w.setElement( gi, 2 * i ); + } + + EXPECT_TRUE( u == u ); + EXPECT_TRUE( u == v ); + EXPECT_TRUE( v == u ); + EXPECT_FALSE( u != v ); + EXPECT_FALSE( v != u ); + EXPECT_TRUE( u != w ); + EXPECT_TRUE( w != u ); + EXPECT_FALSE( u == w ); + EXPECT_FALSE( w == u ); + + v.reset(); + EXPECT_FALSE( u == v ); + u.reset(); + EXPECT_TRUE( u == v ); +} + +TYPED_TEST( DistributedArrayTest, containsValue ) +{ + using IndexType = typename TestFixture::IndexType; + + const auto localRange = this->distributedArray.getLocalRange(); + + for( int i = 0; i < this->distributedArray.getLocalArrayView().getSize(); i++ ) { + const IndexType gi = localRange.getGlobalIndex( i ); + this->distributedArray.setElement( gi, i % 10 ); + } + + for( int i = 0; i < 10; i++ ) + EXPECT_TRUE( this->distributedArray.containsValue( i ) ); + + for( int i = 10; i < 20; i++ ) + EXPECT_FALSE( this->distributedArray.containsValue( i ) ); +} + +TYPED_TEST( DistributedArrayTest, containsOnlyValue ) +{ + using IndexType = typename TestFixture::IndexType; + + const auto localRange = this->distributedArray.getLocalRange(); + + for( int i = 0; i < this->distributedArray.getLocalArrayView().getSize(); i++ ) { + const IndexType gi = localRange.getGlobalIndex( i ); + this->distributedArray.setElement( gi, i % 10 ); + } + + for( int i = 0; i < 20; i++ ) + EXPECT_FALSE( this->distributedArray.containsOnlyValue( i ) ); + + this->distributedArray.setValue( 100 ); + EXPECT_TRUE( this->distributedArray.containsOnlyValue( 100 ) ); +} + +TYPED_TEST( DistributedArrayTest, boolOperator ) +{ + EXPECT_GT( this->distributedArray.getSize(), 0 ); + EXPECT_TRUE( this->distributedArray ); + this->distributedArray.reset(); + EXPECT_EQ( this->distributedArray.getSize(), 0 ); + EXPECT_FALSE( this->distributedArray ); +} + +#endif // HAVE_GTEST + + +#if (defined(HAVE_GTEST) && defined(HAVE_MPI)) +using CommunicatorType = Communicators::MpiCommunicator; + +#include + +class MinimalistBufferedPrinter +: public ::testing::EmptyTestEventListener +{ +private: + std::stringstream sout; + +public: + // Called before a test starts. + virtual void OnTestStart(const ::testing::TestInfo& test_info) + { + sout << test_info.test_case_name() << "." << test_info.name() << " Start." << std::endl; + } + + // Called after a failed assertion or a SUCCEED() invocation. + virtual void OnTestPartResult(const ::testing::TestPartResult& test_part_result) + { + sout << (test_part_result.failed() ? "====Failure=== " : "===Success=== ") + << test_part_result.file_name() << " " + << test_part_result.line_number() <listeners(); + + delete listeners.Release(listeners.default_result_printer()); + listeners.Append(new MinimalistBufferedPrinter); + + Communicators::ScopedInitializer< CommunicatorType > mpi(argc, argv); + #endif + return RUN_ALL_TESTS(); +#else + throw GtestMissingError(); +#endif +} diff --git a/src/UnitTests/DistributedContainers/DistributedMatrixTest.cpp b/src/UnitTests/DistributedContainers/DistributedMatrixTest.cpp new file mode 100644 index 000000000..e422af778 --- /dev/null +++ b/src/UnitTests/DistributedContainers/DistributedMatrixTest.cpp @@ -0,0 +1 @@ +#include "DistributedMatrixTest.h" diff --git a/src/UnitTests/DistributedContainers/DistributedMatrixTest.cu b/src/UnitTests/DistributedContainers/DistributedMatrixTest.cu new file mode 100644 index 000000000..e422af778 --- /dev/null +++ b/src/UnitTests/DistributedContainers/DistributedMatrixTest.cu @@ -0,0 +1 @@ +#include "DistributedMatrixTest.h" diff --git a/src/UnitTests/DistributedContainers/DistributedMatrixTest.h b/src/UnitTests/DistributedContainers/DistributedMatrixTest.h new file mode 100644 index 000000000..80c018bc8 --- /dev/null +++ b/src/UnitTests/DistributedContainers/DistributedMatrixTest.h @@ -0,0 +1,296 @@ +/*************************************************************************** + DistributedMatrixTest.h - description + ------------------- + begin : Sep 10, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +template< typename Vector > +void setLinearSequence( Vector& deviceVector, typename Vector::RealType offset = 0 ) +{ + typename Vector::HostType a; + a.setLike( deviceVector ); + for( int i = 0; i < a.getLocalVectorView().getSize(); i++ ) { + const auto gi = a.getLocalRange().getGlobalIndex( i ); + a[ gi ] = gi + offset; + } + deviceVector = a; +} + +template< typename Matrix, typename RowLengths > +void setMatrix( Matrix& matrix, const RowLengths& rowLengths ) +{ + typename Matrix::HostType hostMatrix; + typename RowLengths::HostType hostRowLengths; + hostMatrix.setLike( matrix ); + hostRowLengths = rowLengths; + hostMatrix.setCompressedRowLengths( hostRowLengths ); + + for( int i = 0; i < hostMatrix.getLocalMatrix().getRows(); i++ ) { + const auto gi = hostMatrix.getLocalRowRange().getGlobalIndex( i ); + for( int j = 0; j < hostRowLengths[ gi ]; j++ ) + hostMatrix.setElement( gi, hostMatrix.getColumns() - j - 1, 1 ); + } + + matrix = hostMatrix; +} + +#ifdef HAVE_GTEST +#include + +#include +#include +#include +#include +#include +#include + +using namespace TNL; +using namespace TNL::DistributedContainers; + +/* + * Light check of DistributedMatrix. + * + * - Number of processes is not limited. + * - Global size is hardcoded as 97 to force non-uniform distribution. + * - Communication group is hardcoded as AllGroup -- it may be changed as needed. + * - Matrix format is hardcoded as CSR -- it should be possible to change it to + * any other format which does not include padding zeros in the getRowLength() + * result. + */ +template< typename DistributedMatrix > +class DistributedMatrixTest +: public ::testing::Test +{ +protected: + using RealType = typename DistributedMatrix::RealType; + using DeviceType = typename DistributedMatrix::DeviceType; + using CommunicatorType = typename DistributedMatrix::CommunicatorType; + using IndexType = typename DistributedMatrix::IndexType; + using DistributedMatrixType = DistributedMatrix; + + using RowLengthsVector = typename DistributedMatrixType::CompressedRowLengthsVector; + using GlobalVector = Containers::Vector< RealType, DeviceType, IndexType >; + using DistributedVector = DistributedContainers::DistributedVector< RealType, DeviceType, IndexType, CommunicatorType >; + + const int globalSize = 97; // prime number to force non-uniform distribution + + const typename CommunicatorType::CommunicationGroup group = CommunicatorType::AllGroup; + + const int rank = CommunicatorType::GetRank(group); + const int nproc = CommunicatorType::GetSize(group); + + DistributedMatrixType matrix; + + RowLengthsVector rowLengths; + + DistributedMatrixTest() + { + using LocalRangeType = typename DistributedMatrix::LocalRangeType; + const LocalRangeType localRange = DistributedContainers::Partitioner< IndexType, CommunicatorType >::splitRange( globalSize, group ); + matrix.setDistribution( localRange, globalSize, globalSize, group ); + rowLengths.setDistribution( localRange, globalSize, group ); + + EXPECT_EQ( matrix.getLocalRowRange(), localRange ); + EXPECT_EQ( matrix.getCommunicationGroup(), group ); + + setLinearSequence( rowLengths, 1 ); + } +}; + +// types for which DistributedMatrixTest is instantiated +using DistributedMatrixTypes = ::testing::Types< + DistributedMatrix< Matrices::CSR< double, Devices::Host, int >, Communicators::MpiCommunicator >, + DistributedMatrix< Matrices::CSR< double, Devices::Host, int >, Communicators::NoDistrCommunicator > +#ifdef HAVE_CUDA + , + DistributedMatrix< Matrices::CSR< double, Devices::Cuda, int >, Communicators::MpiCommunicator >, + DistributedMatrix< Matrices::CSR< double, Devices::Cuda, int >, Communicators::NoDistrCommunicator > +#endif +>; + +TYPED_TEST_CASE( DistributedMatrixTest, DistributedMatrixTypes ); + +TYPED_TEST( DistributedMatrixTest, checkSumOfLocalSizes ) +{ + using CommunicatorType = typename TestFixture::CommunicatorType; + + const int localSize = this->matrix.getLocalMatrix().getRows(); + int sumOfLocalSizes = 0; + CommunicatorType::Allreduce( &localSize, &sumOfLocalSizes, 1, MPI_SUM, this->group ); + EXPECT_EQ( sumOfLocalSizes, this->globalSize ); + EXPECT_EQ( this->matrix.getRows(), this->globalSize ); +} + +TYPED_TEST( DistributedMatrixTest, setLike ) +{ + using DistributedMatrixType = typename TestFixture::DistributedMatrixType; + + EXPECT_EQ( this->matrix.getRows(), this->globalSize ); + EXPECT_EQ( this->matrix.getColumns(), this->globalSize ); + DistributedMatrixType copy; + EXPECT_EQ( copy.getRows(), 0 ); + EXPECT_EQ( copy.getColumns(), 0 ); + copy.setLike( this->matrix ); + EXPECT_EQ( copy.getRows(), this->globalSize ); + EXPECT_EQ( copy.getColumns(), this->globalSize ); +} + +TYPED_TEST( DistributedMatrixTest, reset ) +{ + EXPECT_EQ( this->matrix.getRows(), this->globalSize ); + EXPECT_EQ( this->matrix.getColumns(), this->globalSize ); + EXPECT_GT( this->matrix.getLocalMatrix().getRows(), 0 ); + this->matrix.reset(); + EXPECT_EQ( this->matrix.getRows(), 0 ); + EXPECT_EQ( this->matrix.getColumns(), 0 ); + EXPECT_EQ( this->matrix.getLocalMatrix().getRows(), 0 ); +} + +TYPED_TEST( DistributedMatrixTest, setCompressedRowLengths ) +{ + for( int i = 0; i < this->matrix.getLocalMatrix().getRows(); i++ ) { + const auto gi = this->matrix.getLocalRowRange().getGlobalIndex( i ); + EXPECT_EQ( this->matrix.getRowLength( gi ), 0 ); + EXPECT_EQ( this->matrix.getLocalMatrix().getRowLength( i ), 0 ); + } + this->matrix.setCompressedRowLengths( this->rowLengths ); + for( int i = 0; i < this->matrix.getLocalMatrix().getRows(); i++ ) { + const auto gi = this->matrix.getLocalRowRange().getGlobalIndex( i ); + EXPECT_EQ( this->matrix.getRowLength( gi ), gi + 1 ); + EXPECT_EQ( this->matrix.getLocalMatrix().getRowLength( i ), gi + 1 ); + } +} + +TYPED_TEST( DistributedMatrixTest, getCompressedRowLengths ) +{ + using RowLengthsVector = typename TestFixture::RowLengthsVector; + + this->matrix.setCompressedRowLengths( this->rowLengths ); + RowLengthsVector output; + this->matrix.getCompressedRowLengths( output ); + EXPECT_EQ( output, this->rowLengths ); +} + +TYPED_TEST( DistributedMatrixTest, setGetElement ) +{ + // NOTE: the test is very slow for CUDA, but there is no reason it should fail + // while it works for Host, so we just skip it. + if( std::is_same< typename TestFixture::DeviceType, Devices::Cuda >::value ) + return; + + this->matrix.setCompressedRowLengths( this->rowLengths ); + for( int i = 0; i < this->matrix.getLocalMatrix().getRows(); i++ ) { + const auto gi = this->matrix.getLocalRowRange().getGlobalIndex( i ); + for( int j = 0; j < this->rowLengths.getElement( gi ); j++ ) + this->matrix.setElement( gi, j, gi + j ); + } + for( int i = 0; i < this->matrix.getLocalMatrix().getRows(); i++ ) { + const auto gi = this->matrix.getLocalRowRange().getGlobalIndex( i ); + for( int j = 0; j < this->rowLengths.getElement( gi ); j++ ) { + EXPECT_EQ( this->matrix.getElement( gi, j ), gi + j ); + EXPECT_EQ( this->matrix.getLocalMatrix().getElement( i, j ), gi + j ); + } + } +} + +// TODO: setElementFast, getElementFast + +// TODO: setRowFast, getRowFast + +// TODO: getRow (const and non-const) + +TYPED_TEST( DistributedMatrixTest, vectorProduct_globalInput ) +{ + using GlobalVector = typename TestFixture::GlobalVector; + using DistributedVector = typename TestFixture::DistributedVector; + + this->matrix.setCompressedRowLengths( this->rowLengths ); + setMatrix( this->matrix, this->rowLengths ); + + GlobalVector inVector( this->globalSize ); + inVector.setValue( 1 ); + DistributedVector outVector( this->matrix.getLocalRowRange(), this->globalSize, this->matrix.getCommunicationGroup() ); + this->matrix.vectorProduct( inVector, outVector ); + + EXPECT_EQ( outVector, this->rowLengths ); +} + +TYPED_TEST( DistributedMatrixTest, vectorProduct_distributedInput ) +{ + using DistributedVector = typename TestFixture::DistributedVector; + + this->matrix.setCompressedRowLengths( this->rowLengths ); + setMatrix( this->matrix, this->rowLengths ); + + DistributedVector inVector( this->matrix.getLocalRowRange(), this->globalSize, this->matrix.getCommunicationGroup() ); + inVector.setValue( 1 ); + DistributedVector outVector( this->matrix.getLocalRowRange(), this->globalSize, this->matrix.getCommunicationGroup() ); + this->matrix.vectorProduct( inVector, outVector ); + + EXPECT_EQ( outVector, this->rowLengths ); +} + +#endif // HAVE_GTEST + + +#if (defined(HAVE_GTEST) && defined(HAVE_MPI)) +using CommunicatorType = Communicators::MpiCommunicator; + +#include + +class MinimalistBufferedPrinter +: public ::testing::EmptyTestEventListener +{ +private: + std::stringstream sout; + +public: + // Called before a test starts. + virtual void OnTestStart(const ::testing::TestInfo& test_info) + { + sout << test_info.test_case_name() << "." << test_info.name() << " Start." << std::endl; + } + + // Called after a failed assertion or a SUCCEED() invocation. + virtual void OnTestPartResult(const ::testing::TestPartResult& test_part_result) + { + sout << (test_part_result.failed() ? "====Failure=== " : "===Success=== ") + << test_part_result.file_name() << " " + << test_part_result.line_number() <listeners(); + + delete listeners.Release(listeners.default_result_printer()); + listeners.Append(new MinimalistBufferedPrinter); + + Communicators::ScopedInitializer< CommunicatorType > mpi(argc, argv); + #endif + return RUN_ALL_TESTS(); +#else + throw GtestMissingError(); +#endif +} diff --git a/src/UnitTests/DistributedContainers/DistributedVectorTest.cpp b/src/UnitTests/DistributedContainers/DistributedVectorTest.cpp new file mode 100644 index 000000000..5b0c61c85 --- /dev/null +++ b/src/UnitTests/DistributedContainers/DistributedVectorTest.cpp @@ -0,0 +1 @@ +#include "DistributedVectorTest.h" diff --git a/src/UnitTests/DistributedContainers/DistributedVectorTest.cu b/src/UnitTests/DistributedContainers/DistributedVectorTest.cu new file mode 100644 index 000000000..5b0c61c85 --- /dev/null +++ b/src/UnitTests/DistributedContainers/DistributedVectorTest.cu @@ -0,0 +1 @@ +#include "DistributedVectorTest.h" diff --git a/src/UnitTests/DistributedContainers/DistributedVectorTest.h b/src/UnitTests/DistributedContainers/DistributedVectorTest.h new file mode 100644 index 000000000..30732cfa5 --- /dev/null +++ b/src/UnitTests/DistributedContainers/DistributedVectorTest.h @@ -0,0 +1,411 @@ +/*************************************************************************** + DistributedVectorTest.h - description + ------------------- + begin : Sep 6, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +template< typename Vector > +void setLinearSequence( Vector& deviceVector ) +{ + typename Vector::HostType a; + a.setLike( deviceVector ); + for( int i = 0; i < a.getLocalVectorView().getSize(); i++ ) { + const auto gi = a.getLocalRange().getGlobalIndex( i ); + a[ gi ] = gi; + } + deviceVector = a; +} + +template< typename Vector > +void setConstantSequence( Vector& deviceVector, + typename Vector::RealType v ) +{ + deviceVector.setValue( v ); +} + +template< typename Vector > +void setNegativeLinearSequence( Vector& deviceVector ) +{ + typename Vector::HostType a; + a.setLike( deviceVector ); + for( int i = 0; i < a.getLocalVectorView().getSize(); i++ ) { + const auto gi = a.getLocalRange().getGlobalIndex( i ); + a[ gi ] = -gi; + } + deviceVector = a; +} + +#ifdef HAVE_GTEST +#include + +#include + +#include +#include +#include +#include +#include +#include + +using namespace TNL; +using namespace TNL::DistributedContainers; + +/* + * Light check of DistributedVector. + * + * - Number of processes is not limited. + * - Global size is hardcoded as 97 to force non-uniform distribution. + * - Communication group is hardcoded as AllGroup -- it may be changed as needed. + */ +template< typename DistributedVector > +class DistributedVectorTest +: public ::testing::Test +{ +protected: + using RealType = typename DistributedVector::RealType; + using DeviceType = typename DistributedVector::DeviceType; + using CommunicatorType = typename DistributedVector::CommunicatorType; + using IndexType = typename DistributedVector::IndexType; + using DistributedVectorType = DistributedVector; + using VectorViewType = typename DistributedVectorType::LocalVectorViewType; + using DistributedVectorView = DistributedContainers::DistributedVectorView< RealType, DeviceType, IndexType, CommunicatorType >; + + const int globalSize = 97; // prime number to force non-uniform distribution + + const typename CommunicatorType::CommunicationGroup group = CommunicatorType::AllGroup; + + DistributedVectorType x, y, z; + + DistributedVectorView x_view, y_view, z_view; + + const int rank = CommunicatorType::GetRank(group); + const int nproc = CommunicatorType::GetSize(group); + + DistributedVectorTest() + { + using LocalRangeType = typename DistributedVector::LocalRangeType; + const LocalRangeType localRange = DistributedContainers::Partitioner< IndexType, CommunicatorType >::splitRange( globalSize, group ); + x.setDistribution( localRange, globalSize, group ); + y.setDistribution( localRange, globalSize, group ); + z.setDistribution( localRange, globalSize, group ); + + x_view.bind( x ); + y_view.bind( y ); + z_view.bind( z ); + + setConstantSequence( x, 1 ); + setLinearSequence( y ); + setNegativeLinearSequence( z ); + } +}; + +// types for which DistributedVectorTest is instantiated +using DistributedVectorTypes = ::testing::Types< + DistributedVector< double, Devices::Host, int, Communicators::MpiCommunicator >, + DistributedVector< double, Devices::Host, int, Communicators::NoDistrCommunicator > +#ifdef HAVE_CUDA + , + DistributedVector< double, Devices::Cuda, int, Communicators::MpiCommunicator >, + DistributedVector< double, Devices::Cuda, int, Communicators::NoDistrCommunicator > +#endif +>; + +TYPED_TEST_CASE( DistributedVectorTest, DistributedVectorTypes ); + +TYPED_TEST( DistributedVectorTest, max ) +{ + EXPECT_EQ( this->x.max(), 1 ); + EXPECT_EQ( this->y.max(), this->globalSize - 1 ); + EXPECT_EQ( this->z.max(), 0 ); + + EXPECT_EQ( this->x_view.max(), 1 ); + EXPECT_EQ( this->y_view.max(), this->globalSize - 1 ); + EXPECT_EQ( this->z_view.max(), 0 ); +} + +TYPED_TEST( DistributedVectorTest, min ) +{ + EXPECT_EQ( this->x.min(), 1 ); + EXPECT_EQ( this->y.min(), 0 ); + EXPECT_EQ( this->z.min(), 1 - this->globalSize ); + + EXPECT_EQ( this->x_view.min(), 1 ); + EXPECT_EQ( this->y_view.min(), 0 ); + EXPECT_EQ( this->z_view.min(), 1 - this->globalSize ); +} + +TYPED_TEST( DistributedVectorTest, absMax ) +{ + EXPECT_EQ( this->x.absMax(), 1 ); + EXPECT_EQ( this->y.absMax(), this->globalSize - 1 ); + EXPECT_EQ( this->z.absMax(), this->globalSize - 1 ); + + EXPECT_EQ( this->x_view.absMax(), 1 ); + EXPECT_EQ( this->y_view.absMax(), this->globalSize - 1 ); + EXPECT_EQ( this->z_view.absMax(), this->globalSize - 1 ); +} + +TYPED_TEST( DistributedVectorTest, absMin ) +{ + EXPECT_EQ( this->x.absMin(), 1 ); + EXPECT_EQ( this->y.absMin(), 0 ); + EXPECT_EQ( this->z.absMin(), 0 ); + + EXPECT_EQ( this->x_view.absMin(), 1 ); + EXPECT_EQ( this->y_view.absMin(), 0 ); + EXPECT_EQ( this->z_view.absMin(), 0 ); +} + +TYPED_TEST( DistributedVectorTest, lpNorm ) +{ + using RealType = typename TestFixture::RealType; + + const RealType epsilon = 64 * std::numeric_limits< RealType >::epsilon(); + const RealType expectedL1norm = this->globalSize; + const RealType expectedL2norm = std::sqrt( this->globalSize ); + const RealType expectedL3norm = std::cbrt( this->globalSize ); + + EXPECT_EQ( this->x.lpNorm( 1.0 ), expectedL1norm ); + EXPECT_EQ( this->x.lpNorm( 2.0 ), expectedL2norm ); + EXPECT_NEAR( this->x.lpNorm( 3.0 ), expectedL3norm, epsilon ); + + EXPECT_EQ( this->x_view.lpNorm( 1.0 ), expectedL1norm ); + EXPECT_EQ( this->x_view.lpNorm( 2.0 ), expectedL2norm ); + EXPECT_NEAR( this->x_view.lpNorm( 3.0 ), expectedL3norm, epsilon ); +} + +TYPED_TEST( DistributedVectorTest, sum ) +{ + EXPECT_EQ( this->x.sum(), this->globalSize ); + EXPECT_EQ( this->y.sum(), 0.5 * this->globalSize * ( this->globalSize - 1 ) ); + EXPECT_EQ( this->z.sum(), - 0.5 * this->globalSize * ( this->globalSize - 1 ) ); + + EXPECT_EQ( this->x_view.sum(), this->globalSize ); + EXPECT_EQ( this->y_view.sum(), 0.5 * this->globalSize * ( this->globalSize - 1 ) ); + EXPECT_EQ( this->z_view.sum(), - 0.5 * this->globalSize * ( this->globalSize - 1 ) ); +} + +TYPED_TEST( DistributedVectorTest, differenceMax ) +{ + EXPECT_EQ( this->x.differenceMax( this->y ), 1 ); + EXPECT_EQ( this->y.differenceMax( this->x ), this->globalSize - 2 ); + + EXPECT_EQ( this->x_view.differenceMax( this->y_view ), 1 ); + EXPECT_EQ( this->y_view.differenceMax( this->x_view ), this->globalSize - 2 ); +} + +TYPED_TEST( DistributedVectorTest, differenceMin ) +{ + EXPECT_EQ( this->x.differenceMin( this->y ), 2 - this->globalSize ); + EXPECT_EQ( this->y.differenceMin( this->x ), -1 ); + + EXPECT_EQ( this->x_view.differenceMin( this->y_view ), 2 - this->globalSize ); + EXPECT_EQ( this->y_view.differenceMin( this->x_view ), -1 ); +} + +TYPED_TEST( DistributedVectorTest, differenceAbsMax ) +{ + EXPECT_EQ( this->x.differenceAbsMax( this->y ), this->globalSize - 2 ); + EXPECT_EQ( this->y.differenceAbsMax( this->x ), this->globalSize - 2 ); + + EXPECT_EQ( this->x_view.differenceAbsMax( this->y_view ), this->globalSize - 2 ); + EXPECT_EQ( this->y_view.differenceAbsMax( this->x_view ), this->globalSize - 2 ); +} + +TYPED_TEST( DistributedVectorTest, differenceAbsMin ) +{ + EXPECT_EQ( this->x.differenceAbsMin( this->y ), 0 ); + EXPECT_EQ( this->y.differenceAbsMin( this->x ), 0 ); + + EXPECT_EQ( this->x_view.differenceAbsMin( this->y_view ), 0 ); + EXPECT_EQ( this->y_view.differenceAbsMin( this->x_view ), 0 ); +} + +TYPED_TEST( DistributedVectorTest, differenceLpNorm ) +{ + using RealType = typename TestFixture::RealType; + + this->x.setValue( 2 ); + this->y.setValue( 1 ); + const RealType epsilon = 64 * std::numeric_limits< RealType >::epsilon(); + const RealType expectedL1norm = this->globalSize; + const RealType expectedL2norm = std::sqrt( this->globalSize ); + const RealType expectedL3norm = std::cbrt( this->globalSize ); + + EXPECT_EQ( this->x.differenceLpNorm( this->y, 1.0 ), expectedL1norm ); + EXPECT_EQ( this->x.differenceLpNorm( this->y, 2.0 ), expectedL2norm ); + EXPECT_NEAR( this->x.differenceLpNorm( this->y, 3.0 ), expectedL3norm, epsilon ); + + EXPECT_EQ( this->x_view.differenceLpNorm( this->y_view, 1.0 ), expectedL1norm ); + EXPECT_EQ( this->x_view.differenceLpNorm( this->y_view, 2.0 ), expectedL2norm ); + EXPECT_NEAR( this->x_view.differenceLpNorm( this->y_view, 3.0 ), expectedL3norm, epsilon ); +} + +TYPED_TEST( DistributedVectorTest, differenceSum ) +{ + EXPECT_EQ( this->x.differenceSum( this->x ), 0 ); + EXPECT_EQ( this->y.differenceSum( this->x ), 0.5 * this->globalSize * ( this->globalSize - 1 ) - this->globalSize ); + EXPECT_EQ( this->y.differenceSum( this->y ), 0 ); + + EXPECT_EQ( this->x_view.differenceSum( this->x_view ), 0 ); + EXPECT_EQ( this->y_view.differenceSum( this->x_view ), 0.5 * this->globalSize * ( this->globalSize - 1 ) - this->globalSize ); + EXPECT_EQ( this->y_view.differenceSum( this->y_view ), 0 ); +} + +TYPED_TEST( DistributedVectorTest, scalarMultiplication ) +{ + this->y *= 2; + for( int i = 0; i < this->y.getLocalVectorView().getSize(); i++ ) { + const auto gi = this->y.getLocalRange().getGlobalIndex( i ); + EXPECT_EQ( this->y.getElement( gi ), 2 * gi ); + } + + this->y.scalarMultiplication( 2 ); + for( int i = 0; i < this->y.getLocalVectorView().getSize(); i++ ) { + const auto gi = this->y.getLocalRange().getGlobalIndex( i ); + EXPECT_EQ( this->y.getElement( gi ), 4 * gi ); + } + + setLinearSequence( this->y ); + + this->y_view *= 2; + for( int i = 0; i < this->y_view.getLocalVectorView().getSize(); i++ ) { + const auto gi = this->y_view.getLocalRange().getGlobalIndex( i ); + EXPECT_EQ( this->y_view.getElement( gi ), 2 * gi ); + } + + this->y_view.scalarMultiplication( 2 ); + for( int i = 0; i < this->y_view.getLocalVectorView().getSize(); i++ ) { + const auto gi = this->y_view.getLocalRange().getGlobalIndex( i ); + EXPECT_EQ( this->y_view.getElement( gi ), 4 * gi ); + } +} + +TYPED_TEST( DistributedVectorTest, scalarProduct ) +{ + EXPECT_EQ( this->x.scalarProduct( this->x ), this->globalSize ); + EXPECT_EQ( this->x.scalarProduct( this->y ), 0.5 * this->globalSize * ( this->globalSize - 1 ) ); + EXPECT_EQ( this->y.scalarProduct( this->x ), 0.5 * this->globalSize * ( this->globalSize - 1 ) ); + EXPECT_EQ( this->x.scalarProduct( this->z ), - 0.5 * this->globalSize * ( this->globalSize - 1 ) ); + EXPECT_EQ( this->z.scalarProduct( this->x ), - 0.5 * this->globalSize * ( this->globalSize - 1 ) ); + + EXPECT_EQ( this->x_view.scalarProduct( this->x_view ), this->globalSize ); + EXPECT_EQ( this->x_view.scalarProduct( this->y_view ), 0.5 * this->globalSize * ( this->globalSize - 1 ) ); + EXPECT_EQ( this->y_view.scalarProduct( this->x_view ), 0.5 * this->globalSize * ( this->globalSize - 1 ) ); + EXPECT_EQ( this->x_view.scalarProduct( this->z_view ), - 0.5 * this->globalSize * ( this->globalSize - 1 ) ); + EXPECT_EQ( this->z_view.scalarProduct( this->x_view ), - 0.5 * this->globalSize * ( this->globalSize - 1 ) ); +} + +TYPED_TEST( DistributedVectorTest, addVector ) +{ + this->x.addVector( this->y, 3.0, 1.0 ); + for( int i = 0; i < this->y.getLocalVectorView().getSize(); i++ ) { + const auto gi = this->y.getLocalRange().getGlobalIndex( i ); + EXPECT_EQ( this->x.getElement( gi ), 1 + 3 * gi ); + } + + this->y += this->z; + for( int i = 0; i < this->y.getLocalVectorView().getSize(); i++ ) { + const auto gi = this->y.getLocalRange().getGlobalIndex( i ); + EXPECT_EQ( this->y.getElement( gi ), 0 ); + } + + setConstantSequence( this->x, 1 ); + setLinearSequence( this->y ); + + this->x_view.addVector( this->y_view, 3.0, 1.0 ); + for( int i = 0; i < this->y_view.getLocalVectorView().getSize(); i++ ) { + const auto gi = this->y_view.getLocalRange().getGlobalIndex( i ); + EXPECT_EQ( this->x_view.getElement( gi ), 1 + 3 * gi ); + } + + this->y_view += this->z_view; + for( int i = 0; i < this->y_view.getLocalVectorView().getSize(); i++ ) { + const auto gi = this->y_view.getLocalRange().getGlobalIndex( i ); + EXPECT_EQ( this->y_view.getElement( gi ), 0 ); + } +} + +TYPED_TEST( DistributedVectorTest, addVectors ) +{ + this->x.addVectors( this->y, 3.0, this->z, 1.0, 2.0 ); + for( int i = 0; i < this->y.getLocalVectorView().getSize(); i++ ) { + const auto gi = this->y.getLocalRange().getGlobalIndex( i ); + EXPECT_EQ( this->x.getElement( gi ), 2 + 3 * gi - gi ); + } + + setConstantSequence( this->x, 1 ); + + this->x_view.addVectors( this->y_view, 3.0, this->z_view, 1.0, 2.0 ); + for( int i = 0; i < this->y_view.getLocalVectorView().getSize(); i++ ) { + const auto gi = this->y_view.getLocalRange().getGlobalIndex( i ); + EXPECT_EQ( this->x_view.getElement( gi ), 2 + 3 * gi - gi ); + } +} + +// TODO: distributed prefix sum + +#endif // HAVE_GTEST + + +#if (defined(HAVE_GTEST) && defined(HAVE_MPI)) +using CommunicatorType = Communicators::MpiCommunicator; + +#include + +class MinimalistBufferedPrinter +: public ::testing::EmptyTestEventListener +{ +private: + std::stringstream sout; + +public: + // Called before a test starts. + virtual void OnTestStart(const ::testing::TestInfo& test_info) + { + sout << test_info.test_case_name() << "." << test_info.name() << " Start." << std::endl; + } + + // Called after a failed assertion or a SUCCEED() invocation. + virtual void OnTestPartResult(const ::testing::TestPartResult& test_part_result) + { + sout << (test_part_result.failed() ? "====Failure=== " : "===Success=== ") + << test_part_result.file_name() << " " + << test_part_result.line_number() <listeners(); + + delete listeners.Release(listeners.default_result_printer()); + listeners.Append(new MinimalistBufferedPrinter); + + Communicators::ScopedInitializer< CommunicatorType > mpi(argc, argv); + #endif + return RUN_ALL_TESTS(); +#else + throw GtestMissingError(); +#endif +} diff --git a/src/UnitTests/FileNameTest.cpp b/src/UnitTests/FileNameTest.cpp new file mode 100644 index 000000000..3f71be146 --- /dev/null +++ b/src/UnitTests/FileNameTest.cpp @@ -0,0 +1,47 @@ +/*************************************************************************** + FileNameTest.cpp - description + ------------------- + begin : Oct 17, 2018 + copyright : (C) 2018 by Tomas Oberhuber + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by Nina Dzugasova + +#ifdef HAVE_GTEST +#include +#endif + +#include + +using namespace TNL; + +#ifdef HAVE_GTEST +TEST( FileNameTest, Constructor ) +{ + /*String str1( "string1" ); + String str2( "xxxstring2", 3 ); + String str3( "string3xxx", 0, 3 ); + String str4( "xxxstring4xxx", 3, 3 ); + + EXPECT_EQ( strcmp( str1.getString(), "string1" ), 0 ); + EXPECT_EQ( strcmp( str2.getString(), "string2" ), 0 ); + EXPECT_EQ( strcmp( str3.getString(), "string3" ), 0 ); + EXPECT_EQ( strcmp( str4.getString(), "string4" ), 0 );*/ +} +#endif + + +#include "GtestMissingError.h" +int main( int argc, char* argv[] ) +{ +#ifdef HAVE_GTEST + ::testing::InitGoogleTest( &argc, argv ); + return RUN_ALL_TESTS(); +#else + throw GtestMissingError(); +#endif +} + diff --git a/src/UnitTests/StringTest.cpp b/src/UnitTests/StringTest.cpp index ff95a8db8..f6664673e 100644 --- a/src/UnitTests/StringTest.cpp +++ b/src/UnitTests/StringTest.cpp @@ -308,6 +308,14 @@ TEST( StringTest, split ) String( "abracadabra" ).split( list, 'A' ); ASSERT_EQ( list.getSize(), 1 ); EXPECT_EQ( list[ 0 ], "abracadabra" ); + + /// !!!! + String( "a,,b,c" ).split( list, ',' ); + ASSERT_EQ( list.getSize(), 4 ); + EXPECT_EQ( list[ 0 ], "a" ); + EXPECT_EQ( list[ 1 ], "" ); + EXPECT_EQ( list[ 2 ], "b" ); + EXPECT_EQ( list[ 3 ], "c" ); } TEST( StringTest, SaveLoad ) @@ -324,6 +332,23 @@ TEST( StringTest, SaveLoad ) EXPECT_EQ( std::remove( "test-file.tnl" ), 0 ); }; + +TEST( StringTest, getLine ) +{ + std::stringstream str; + str << "Line 1" << std::endl; + str << "Line 2" << std::endl; + str.seekg( 0 ); + + String s; + + s.getLine( str ); + EXPECT_EQ( s, "Line 1" ); + + s.getLine( str ); + EXPECT_EQ( s, "Line 2" ); +}; + #endif -- GitLab From 6be27c41aaa15741c094ff8bb5021354eaac5362 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 22 Oct 2018 16:09:40 +0200 Subject: [PATCH 008/111] Added documentation to String. --- src/TNL/String.h | 17 ++++++++++------- src/UnitTests/StringTest.cpp | 8 +++++++- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/TNL/String.h b/src/TNL/String.h index 6e8ab7192..57219562e 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -138,7 +138,7 @@ class String /// This function overloads operator!=(). bool operator!=( char str ) const; - /// \brief Cast to bool operator. + /// \brief Cast to bool operator. Converts string to boolean expression (true or false). operator bool() const; /// \brief Cast to bool with negation operator. @@ -161,25 +161,27 @@ class String /// @param separator Character, which separates substrings in given string. Empty character can not be used. int split( Containers::List< String >& list, const char separator = ' ' ) const; - /// Write to a binary file + /// Writes to a binary file and returns boolean expression based on the success in writing into the file. bool save( File& file ) const; - /// Read from binary file + /// Reads from binary file and returns boolean expression based on the success in reading the file. bool load( File& file ); - //! Broadcast to other nodes in MPI cluster + /// !!! Mozem dat prec??? + // Broadcast to other nodes in MPI cluster // void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); - /// Read one line from given stream. + /// Reads one line from given stream. bool getLine( std::istream& stream ); + ///toto neviem co friend std::ostream& operator<<( std::ostream& stream, const String& str ); protected: - /// Pointer to char ended with zero + /// Pointer to char ended with zero ...Preco? char* string; - /// Length of the allocated piece of memory + /// Length of the allocated piece of memory. int length; @@ -191,6 +193,7 @@ String operator+( char string1, const String& string2 ); /// Returns concatenation of \e string1 and \e string2. String operator+( const char* string1, const String& string2 ); +/// Toto neviem co std::ostream& operator<<( std::ostream& stream, const String& str ); template< typename T > diff --git a/src/UnitTests/StringTest.cpp b/src/UnitTests/StringTest.cpp index f6664673e..9b85bd728 100644 --- a/src/UnitTests/StringTest.cpp +++ b/src/UnitTests/StringTest.cpp @@ -309,7 +309,7 @@ TEST( StringTest, split ) ASSERT_EQ( list.getSize(), 1 ); EXPECT_EQ( list[ 0 ], "abracadabra" ); - /// !!!! + /// !!!! ma problem s prazdnym stringom !!!! String( "a,,b,c" ).split( list, ',' ); ASSERT_EQ( list.getSize(), 4 ); EXPECT_EQ( list[ 0 ], "a" ); @@ -349,6 +349,12 @@ TEST( StringTest, getLine ) EXPECT_EQ( s, "Line 2" ); }; +/*TEST( StringTest, OperatorCudny ) +{ + String str("String1"); + EXPECT_EQ(strcmp(String( "a", str ), "aString1"), 0 ); +};*/ + #endif -- GitLab From 1704a0cb8ed091ce3fd5fa1770bf6ebab3baf67f Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Wed, 24 Oct 2018 16:02:57 +0200 Subject: [PATCH 009/111] Altered documentation of String. Started with examples. --- Doxyfile | 2 +- src/TNL/String.h | 204 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 144 insertions(+), 62 deletions(-) diff --git a/Doxyfile b/Doxyfile index a796c7fe3..649e477a4 100644 --- a/Doxyfile +++ b/Doxyfile @@ -906,7 +906,7 @@ EXCLUDE_SYMBOLS = # that contain example code fragments that are included (see the \include # command). -EXAMPLE_PATH = +EXAMPLE_PATH = src/Examples # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and diff --git a/src/TNL/String.h b/src/TNL/String.h index 8ea736f29..20b065ba2 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -25,25 +25,38 @@ class String; template< typename T > String convertToString( const T& value ); -///// -// Class for managing strings. + class String { public: ///// - /// Basic constructor. - + /// \brief Basic constructor. + /// /// Constructs an empty string object with the length of zero characters. + /// \par Example + /// \include StringExample.cpp + /// \par Output + /// str1 = \n str2 = String(); ///// - /// Constructor with char pointer. - + /// \brief Constructor with char pointer. + /// /// Copies the null-terminated character sequence (C-string) pointed by \e c. - /// Constructs a string initialized with the 8-bit string \e c, excluding the given number of \e prefix_cut_off and \e sufix_cut_off characters. - /// @param prefix_cut_off determines the length of the prefix that is going to be omitted from the string \e c - /// @param sufix_cut_off determines the length of the sufix that is going to be omitted from the string \e c + /// Constructs a string initialized with the 8-bit string \e c, excluding + /// the given number of \e prefix_cut_off and \e sufix_cut_off characters. + /// + /// @param prefix_cut_off Determines the length of the prefix that is going + /// to be omitted from the string \e c. + /// @param sufix_cut_off Determines the length of the sufix that is going + /// to be omitted from the string \e c. + /// + /// \par Example + /// \code String str( "xxstringxxx", 2, 3 ); \endcode + /// + /// \par Output + /// str = string String( const char* c, int prefix_cut_off = 0, int sufix_cut_off = 0 ); @@ -57,9 +70,17 @@ class String static String getType(); ///// - /// Copy constructor. - + /// \brief Copy constructor. + /// /// Constructs a copy of the string \e str. + /// + /// \par Example + /// \code + String str1( "Something" ); + String str2( str1 ); + /// \endcode + /// \par Output + /// str1 = Something \n str2 = Something String( const String& str ); /// Converts anything to a string. @@ -70,7 +91,7 @@ class String setString( convertToString( value ).getString() ); } - /// Destructor. + /// \brief Destructor. ~String(); /// Returns the number of characters in given string. Equivalent to getSize(). @@ -82,116 +103,177 @@ class String /// Returns size of allocated storage for given string. int getAllocatedSize() const; - /// Reserves space for given number of characters (\e size). - /// Requests to allocate storage for given \e size (number of characters). + ///// + /// Reserves space for given \e size. + /// Requests to allocate storage for given \e size. + /// @param size Number of characters. void setSize( int size ); ///// - /// Sets string from given char pointer \e c. - /// @param prefix_cut_off determines the length of the prefix that is going to be omitted from the string \e c - /// @param sufix_cut_off determines the length of the sufix that is going to be omitted from the string \e c + /// \brief Sets string from given char pointer \e c. + /// + /// @param prefix_cut_off determines the length of the prefix that is + /// going to be omitted from the string \e c + /// @param sufix_cut_off determines the length of the sufix that is going + /// to be omitted from the string \e c void setString( const char* c, int prefix_cut_off = 0, int sufix_cut_off = 0 ); - /// Returns pointer to data. It returns the content of the given string. + ///// + /// \brief Returns pointer to data. + /// + /// It returns the content of the given string. The content can not be + /// changed by user. const char* getString() const; - /// Returns pointer to data. + /// \brief Returns pointer to data. + /// + /// It returns the content of the given string. The content can be changed + /// by user. char* getString(); - /// Operator for accesing particular chars of the string. - - ///This function overloads operator[](). It returns a reference to the character at position \e i in given string. + ///// + /// \brief Operator for accesing particular chars of the string. + /// + /// This function overloads operator[](). It returns a reference to + /// the character at position \e i in given string. + /// The character can not be changed be user. const char& operator[]( int i ) const; - /// Operator for accesing particular chars of the string. - - ///It returns the character at the position \e i in given string as a modifiable reference. + /// \brief Operator for accesing particular chars of the string. + /// + /// It returns the character at the position \e i in given string as + /// a modifiable reference. char& operator[]( int i ); ///// - /// Operators for C strings. + // Operators for C strings. - /// This function overloads operator=(). It assigns \e str to this string, replacing its current contents. + /// \brief This function overloads operator=(). + /// + /// It assigns C string \e str to this string, replacing its current contents. String& operator=( const char* str ); - /// This function overloads operator+=(). It appends the string \e str to this string. + /// \brief This function overloads operator+=(). + /// + /// It appends the C string \e str to this string. String& operator+=( const char* str ); - /// This function concatenates strings and returns a newly constructed string object. + /// \brief This function concatenates C strings \e str and returns a newly + /// constructed string object. String operator+( const char* str ) const; - /// This function overloads operator==(). + /// \brief This function overloads operator==(). bool operator==( const char* str ) const; - /// This function overloads operator!=(). + /// \brief This function overloads operator!=(). bool operator!=( const char* str ) const; ///// - /// Operators for Strings. + // Operators for Strings. - /// This function assigns \e str to this string and returns a reference to this string. + /// This function assigns \e str to this string and returns a reference to + /// this string. String& operator=( const String& str ); - /// This function appends the string \e str onto the end of this string and returns a reference to this string. + /// This function appends the string \e str onto the end of this string + /// and returns a reference to this string. String& operator+=( const String& str ); - /// This function concatenates strings and returns a newly constructed string object. + /// This function concatenates strings \e str and returns a newly + /// constructed string object. String operator+( const String& str ) const; - /// This function overloads operator==(). It returns \c true if this string is equal to \e str, otherwise returns \c false. + /// \brief This function overloads operator==(). + /// + /// It returns \c true if this string is equal to \e str, otherwise returns + /// \c false. bool operator==( const String& str ) const; - /// This function overloads operator!=(). It returns \c true if this string is not equal to \e str, otherwise returns \c false. + /// \brief This function overloads operator!=(). + /// + /// It returns \c true if this string is not equal to \e str, otherwise + /// returns \c false. bool operator!=( const String& str ) const; ///// - /// Operators for single characters. + // Operators for single characters. - /// This function overloads operator=(). It assigns character /e str to this string. + /// \brief This function overloads operator=(). + /// + /// It assigns character /e str to this string. String& operator=( char str ); - /// This function overloads operator+=(). It appends character /e str to this string. + /// \brief This function overloads operator+=(). + /// + /// It appends character /e str to this string. String& operator+=( char str ); // This function concatenates strings and returns a newly constructed string object. String operator+( char str ) const; // This function concatenates strings and returns a newly constructed string object. bool operator==( char str ) const; - /// This function overloads operator!=(). + /// \brief This function overloads operator!=(). bool operator!=( char str ) const; - /// Cast to bool operator. - - ///Converts string to boolean expression (true or false). + /// \brief Cast to bool operator. + /// + /// This function overloads operator bool(). It converts string to boolean + /// expression (true or false). operator bool() const; - /// Cast to bool with negation operator. + /// \brief Cast to bool with negation operator. + /// + /// This function overloads operator!(). It converts string to boolean + /// expression (false or true). bool operator!() const; ///// - /// Replaces portion of string. - - ///It replaces section \e pattern from this string with new piece of string \e replaceWith. - ///If parameter \e count is defined, the function makes replacement several times, every time when it finds the same pattern in this string. + /// \brief Replaces portion of string. + /// + /// Replaces section \e pattern from this string with new piece of string \e replaceWith. + /// If parameter \e count is defined, the function makes replacement several times, + /// every time when it finds the same pattern in this string. + /// @param pattern Section of given string that will be replaced. + /// @param replaceWith New piece of string that will be used to replace \e pattern. + /// @param count A whole number that specifies how many replacements should be done. String replace( const String& pattern, const String& replaceWith, int count = 0 ) const; - /// Trims/strips given string. - - /// It removes all spaces from string except for single spaces between words. + ///// + /// \brief Trims/strips given string. + /// + /// Removes all spaces from given string except for single spaces between words. String strip( char strip = ' ' ) const; - /// Splits string into list of strings with respect to given \e separator. - - /// It splits the string into list of substrings wherever \e separator occurs, and returs list of those strings. - /// When \e separator does not appear anywhere in the given string, this function returns a single-element list containing given sting. - /// @param separator Character, which separates substrings in given string. Empty character can not be used. + /// \brief Splits string into list of strings with respect to given \e separator. + /// + /// Splits the string into list of substrings wherever \e separator occurs, + /// and returs list of those strings. When \e separator does not appear + /// anywhere in the given string, this function returns a single-element list + /// containing given sting. + /// @param list Name of list. + /// @param separator Character, which separates substrings in given string. + /// Empty character can not be used. int split( Containers::List< String >& list, const char separator = ' ' ) const; - /// Writes to a binary file and returns boolean expression based on the success in writing into the file. + ///// + /// \brief Function for saving file. + /// + /// Writes to a binary file and returns boolean expression based on the + /// success in writing into the file. bool save( File& file ) const; - /// Reads from binary file and returns boolean expression based on the success in reading the file. + ///// + /// \brief Function for loading from file. + /// + /// Reads from binary file and returns boolean expression based on the + /// success in reading the file. bool load( File& file ); + // Mozem dat prec??? !!!! // Broadcast to other nodes in MPI cluster // void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); - /// Reads one line from given stream. + + ///// + /// \brief Function for getting a line from stream. + /// + /// Reads one line from given stream and returns either the line or boolean + /// expression based on the success in reading the line. bool getLine( std::istream& stream ); ///toto neviem co @@ -201,7 +283,7 @@ class String /// Pointer to char ended with zero ...Preco? char* string; - /// Length of the allocated piece of memory. + /// Length of allocated piece of memory. int length; }; -- GitLab From 955e99f0179f6c7b7c7baa6923b00f613cf29206 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Thu, 25 Oct 2018 16:07:37 +0200 Subject: [PATCH 010/111] Added first examples into String. --- src/TNL/String.h | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/src/TNL/String.h b/src/TNL/String.h index 20b065ba2..9625554ad 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -25,7 +25,13 @@ class String; template< typename T > String convertToString( const T& value ); - +///// +/// \brief Class for managing strings. +/// +/// \par Example +/// \include StringExample.cpp +/// \par Output +/// \include StringOutput.cpp class String { public: @@ -34,10 +40,6 @@ class String /// \brief Basic constructor. /// /// Constructs an empty string object with the length of zero characters. - /// \par Example - /// \include StringExample.cpp - /// \par Output - /// str1 = \n str2 = String(); ///// @@ -51,12 +53,6 @@ class String /// to be omitted from the string \e c. /// @param sufix_cut_off Determines the length of the sufix that is going /// to be omitted from the string \e c. - /// - /// \par Example - /// \code String str( "xxstringxxx", 2, 3 ); \endcode - /// - /// \par Output - /// str = string String( const char* c, int prefix_cut_off = 0, int sufix_cut_off = 0 ); @@ -73,17 +69,12 @@ class String /// \brief Copy constructor. /// /// Constructs a copy of the string \e str. - /// - /// \par Example - /// \code - String str1( "Something" ); - String str2( str1 ); - /// \endcode - /// \par Output - /// str1 = Something \n str2 = Something String( const String& str ); - /// Converts anything to a string. + /// \brief Converts anything to a string. + /// + /// This function converts any type of value into type string. + /// @param value Word of any type (e.g. int, bool, double,...). template< typename T > String( T value ) : string( nullptr ), length( 0 ) @@ -106,6 +97,7 @@ class String ///// /// Reserves space for given \e size. /// Requests to allocate storage for given \e size. + /// It allocates one more byte for the terminating 0. /// @param size Number of characters. void setSize( int size ); @@ -264,7 +256,7 @@ class String bool load( File& file ); - // Mozem dat prec??? !!!! + // !!! Mozem dat prec??? // Broadcast to other nodes in MPI cluster // void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); @@ -286,7 +278,7 @@ class String /// Length of allocated piece of memory. int length; -}; +}; // class String /// Returns concatenation of \e string1 and \e string2. String operator+( char string1, const String& string2 ); -- GitLab From 28121339c89c5f4f663d6520fc521626135e4900 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Oberhuber?= Date: Sat, 27 Oct 2018 21:17:32 +0200 Subject: [PATCH 011/111] Doxygen omits directories without documentation. --- Doxyfile | 18 +++++++++++++++++- generate-doc | 3 ++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index a796c7fe3..8914191e3 100644 --- a/Doxyfile +++ b/Doxyfile @@ -889,7 +889,23 @@ EXCLUDE_SYMLINKS = NO # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS = */Communicators/* \ + */Config/* \ + */Containers/* \ + */Debugging/* \ + */Devices/* \ + */DistributedContainers/* \ + */Exceptions/* \ + */Experimental/* \ + */Functions/* \ + */Images/* \ + */Matrices/* \ + */Meshes/* \ + */Operators/* \ + */Pointers/* \ + */Problems/* \ + */Solvers/* + # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the diff --git a/generate-doc b/generate-doc index 6007851f4..9a2ad0ab9 100755 --- a/generate-doc +++ b/generate-doc @@ -15,6 +15,7 @@ done doxygen if [[ "$INSTALL" == "yes" ]]; then - cp -r Documentation/* ${PREFIX}/share/doc + mkdir -p ${PREFIX}/share/doc/tnl + cp -r Documentation/* ${PREFIX}/share/doc/tnl fi -- GitLab From 515556f4429b24ff48f844c8489fe187e3a23c54 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 29 Oct 2018 13:57:58 +0100 Subject: [PATCH 012/111] String documentation. --- src/Examples/StringExample.cpp | 112 +++++++++++++++++++++++++++++++++ src/Examples/StringExample.out | 40 ++++++++++++ src/TNL/String.h | 4 +- 3 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 src/Examples/StringExample.cpp create mode 100644 src/Examples/StringExample.out diff --git a/src/Examples/StringExample.cpp b/src/Examples/StringExample.cpp new file mode 100644 index 000000000..1297f521f --- /dev/null +++ b/src/Examples/StringExample.cpp @@ -0,0 +1,112 @@ +#include + +using namespace TNL + +int main() +{ + // constructors + String str1; + String str2( "xxstringxxx", 2, 3 ); + String str3( str2 ); // copy constructor + String str4( 28.4 ); // converts to string + + cout << "str1:" << str1 << endl; + cout << "str2:" << str2 << endl; + cout << "str3:" << str3 << endl; + cout << "str4:" << str4 << endl; + + // functions + int size = str3.getSize(); + cout << "size of string:" << size << "bytes" << endl; + + int alloc_size = str3.getAllocatedSize(); + cout << "alloc_size:" << alloc_size << endl; + + int memory = str1.setSize( 256 ); + cout << "memory:" << memory << endl; + + String str + setter = str.setString( "Something new" ); + cout << "setter:" << setter << endl; + + int getter = str4.getString(); + cout << "getter:" << getter << endl; + + String word( computer ) ; + third_letter = word[2]; + cout << "third_letter:" << third_letter << endl; + + // Operators for C Strings + String a( "hello" ); + a = "bye"; + cout << "a:" << a << endl; + + String b( "see" ); + b += " you"; + cout << "b:" << b << endl; + + String c; + c = b + " soon"; + cout << "c:" << c << endl; + + String name( "Jack" ); + if ( name == "Jack" ) cout << "Names are the same." << endl; + + String surname( "Sparrow" ); + if ( surname != "Jones" ) cout << "Surnames are different." << endl; + + // Operators for Strings + String d1( "Cheese" ); + d = d1; + cout << "d:" << d << endl; + + String e( "Mac&" ); + e += d; + cout << "e:" << e << endl; + + String f; + String f1("Tim likes "); + f = f1 + e; + cout << "f:" << f << endl; + + String num1( "one" ); + String num2( "Anyone", 3); + if ( num1 == num2 ) cout << "Numbers are the same." << endl; + + String eq1( "a + b" ); + String eq2( "a" ); + if ( eq1 != eq2 ) cout << "Equations are different." << endl; + + // Operators for single characters + String g; + g = 'y'; + cout << "g:" << g << endl; + + String h( "x" ); + h += g; + cout << "h:" << h << endl; + + String i; + i = 'a' + 'b'; + cout << "i:" << i << endl; + + String letter1( "u" ); + if ( letter1 == "u" ) cout << "Letters are the same." << endl; + + String letter2( "v" ); + if ( letter2 != "w" ) cout << "Letters are different." << endl; + + //Cast to bool operators + String full( "string" ); + if ( full ) cout << "String is not empty." << endl; + + String empty; + if ( !empty ) cout << "String is empty." << endl; + + //replace + String phrase( "Hakuna matata" ); + new_phrase = phrase.replace( "a", "u", 2 ); + cout << "new_phrase:" << new_phrase << endl; + + +} diff --git a/src/Examples/StringExample.out b/src/Examples/StringExample.out new file mode 100644 index 000000000..4bc752b22 --- /dev/null +++ b/src/Examples/StringExample.out @@ -0,0 +1,40 @@ +//constructors +str1: +str2: string +str3: string +str4: 28.4 //string type + +//functions +size of string: 6 bytes +alloc_size: 256 +memory: 512 +setter: Something new +getter: 28.4 +third_letter: m + +// Operators for C Strings +a: bye +b: see you +c: see you soon +Names are the same. +Surnames are different. + +// Operators for Strings +d: Cheese +e: Mac&Cheese +f: Tim likes Mac&Cheese +Numbers are the same. +Equations are different. +// Operators for single characters +g: y +h: xy +i: ab +Letters are the same. +Letters are different. + +//Cast to bool operators +String is not empty. +String is empty. + +//replace +new_phrase: Hukunu matata diff --git a/src/TNL/String.h b/src/TNL/String.h index 9625554ad..6d50116f7 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -96,7 +96,7 @@ class String ///// /// Reserves space for given \e size. - /// Requests to allocate storage for given \e size. + /// Requests to allocate storage space of given \e size to avoid memory reallocation. /// It allocates one more byte for the terminating 0. /// @param size Number of characters. void setSize( int size ); @@ -256,7 +256,7 @@ class String bool load( File& file ); - // !!! Mozem dat prec??? + // !!! Mozem dat prec??? // Broadcast to other nodes in MPI cluster // void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); -- GitLab From 75e29571687824dd406f7396b23aaed69deeb116 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 5 Nov 2018 16:56:24 +0100 Subject: [PATCH 013/111] More StringExamples and added FileNameTest --- src/Examples/StringExample.cpp | 48 ++++++++++++++++++++------- src/Examples/StringExample.out | 16 +++++++-- src/TNL/String.h | 2 +- src/UnitTests/FileNameTest.cpp | 59 ++++++++++++++++++++++++++++------ src/UnitTests/StringTest.cpp | 2 ++ 5 files changed, 104 insertions(+), 23 deletions(-) diff --git a/src/Examples/StringExample.cpp b/src/Examples/StringExample.cpp index 1297f521f..f33da1392 100644 --- a/src/Examples/StringExample.cpp +++ b/src/Examples/StringExample.cpp @@ -81,32 +81,58 @@ int main() String g; g = 'y'; cout << "g:" << g << endl; - + String h( "x" ); h += g; cout << "h:" << h << endl; - + String i; i = 'a' + 'b'; cout << "i:" << i << endl; - + String letter1( "u" ); if ( letter1 == "u" ) cout << "Letters are the same." << endl; - + String letter2( "v" ); if ( letter2 != "w" ) cout << "Letters are different." << endl; - - //Cast to bool operators + + // Cast to bool operators String full( "string" ); if ( full ) cout << "String is not empty." << endl; - + String empty; if ( !empty ) cout << "String is empty." << endl; - - //replace + + // replace String phrase( "Hakuna matata" ); new_phrase = phrase.replace( "a", "u", 2 ); cout << "new_phrase:" << new_phrase << endl; - - + + // strip + String names(" Josh Martin John Marley Charles "); + better_names = names.strip(); + cout << "better_names:" << better_names << endl; + + // split + String dates("3/4/2005;8/7/2011;11/12/2019"); + list_dates = dates.split( list, ';' ); + cout << "list_dates:" << list_dates << endl; + + // save + String("Header").save(my-file.tnl); // saves "Header" into file my-file.tnl + + // load + String strg; + strg.load(my-file.tnl); + cout << "strg:" << strg << endl; + + // get line + std::stringstream text; + text << "Hello!" << std::endl; + text << "What's up?" << std::endl; + + String str; + str.getLine( text ); + cout << "str:" << str << endl; + } diff --git a/src/Examples/StringExample.out b/src/Examples/StringExample.out index 4bc752b22..87170b8a9 100644 --- a/src/Examples/StringExample.out +++ b/src/Examples/StringExample.out @@ -32,9 +32,21 @@ i: ab Letters are the same. Letters are different. -//Cast to bool operators +// Cast to bool operators String is not empty. String is empty. -//replace +// replace new_phrase: Hukunu matata + +// strip +list_dates: 3/4/2005 8/7/2011 11/12/2019 + +// save +true + +// load +strg: Header + +// get line +str: Hello! \ No newline at end of file diff --git a/src/TNL/String.h b/src/TNL/String.h index 6d50116f7..5d9a3f003 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -31,7 +31,7 @@ String convertToString( const T& value ); /// \par Example /// \include StringExample.cpp /// \par Output -/// \include StringOutput.cpp +/// \include StringExample.out class String { public: diff --git a/src/UnitTests/FileNameTest.cpp b/src/UnitTests/FileNameTest.cpp index 3f71be146..38192af05 100644 --- a/src/UnitTests/FileNameTest.cpp +++ b/src/UnitTests/FileNameTest.cpp @@ -15,22 +15,63 @@ #endif #include +#include using namespace TNL; #ifdef HAVE_GTEST TEST( FileNameTest, Constructor ) { - /*String str1( "string1" ); - String str2( "xxxstring2", 3 ); - String str3( "string3xxx", 0, 3 ); - String str4( "xxxstring4xxx", 3, 3 ); - - EXPECT_EQ( strcmp( str1.getString(), "string1" ), 0 ); - EXPECT_EQ( strcmp( str2.getString(), "string2" ), 0 ); - EXPECT_EQ( strcmp( str3.getString(), "string3" ), 0 ); - EXPECT_EQ( strcmp( str4.getString(), "string4" ), 0 );*/ + FileName fname; + + EXPECT_EQ( strcmp( fname.getFileName(), "00000." ), 0 ); +} + +TEST( FileNameTest, Base ) +{ + FileName fname; + fname.setFileNameBase("name"); + + EXPECT_EQ( strcmp( fname.getFileName(), "name00000." ), 0 ); +} + +/*TEST( FileNameTest, Extension ) +{ + FileName fname; + fname.setExtension("tnl"); + + EXPECT_EQ( strcmp( fname.getFileName(), "00000.tnl" ), 0 ); +}*/ + +/*TEST( FileNameTest, Index ) +{ + FileName fname1; + FileName fname2; + fname1.setIndex(1); + fname2.setIndex(50); + + EXPECT_EQ( strcmp( fname1.getFileName(), "00001." ), 0 ); + EXPECT_EQ( strcmp( fname2.getFileName(), "00050." ), 0 ); +}*/ + +/*TEST( FileNameTest, DigitsCount ) +{ + FileName fname; + fname.setDigitsCount(4); + + EXPECT_EQ( strcmp( fname.getFileName(), "0000." ), 0 ); } + +TEST( FileNameTest, AllTogether ) +{ + FileName fname; + fname.setFileNameBase("name"); + fname.setExtension("tnl"); + fname.setIndex(8); + fname.setDigitsCount(3); + + EXPECT_EQ( strcmp( fname.getFileName(), "name008.tnl" ), 0 ); +}*/ #endif diff --git a/src/UnitTests/StringTest.cpp b/src/UnitTests/StringTest.cpp index 232f84161..511bed7a8 100644 --- a/src/UnitTests/StringTest.cpp +++ b/src/UnitTests/StringTest.cpp @@ -8,6 +8,8 @@ /* See Copyright Notice in tnl/Copyright */ +// Implemented by Nina Dzugasova + #ifdef HAVE_GTEST #include #endif -- GitLab From c49c5d49c6d1de7f97b299ef94938be408522de4 Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber Date: Tue, 6 Nov 2018 10:20:48 +0100 Subject: [PATCH 014/111] Fixed FileNameTest compilation. --- src/UnitTests/FileNameTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/UnitTests/FileNameTest.cpp b/src/UnitTests/FileNameTest.cpp index 38192af05..134a5f56a 100644 --- a/src/UnitTests/FileNameTest.cpp +++ b/src/UnitTests/FileNameTest.cpp @@ -24,7 +24,7 @@ TEST( FileNameTest, Constructor ) { FileName fname; - EXPECT_EQ( strcmp( fname.getFileName(), "00000." ), 0 ); + EXPECT_EQ( fname.getFileName(), "00000." ); } TEST( FileNameTest, Base ) @@ -32,7 +32,7 @@ TEST( FileNameTest, Base ) FileName fname; fname.setFileNameBase("name"); - EXPECT_EQ( strcmp( fname.getFileName(), "name00000." ), 0 ); + EXPECT_EQ( fname.getFileName(), "name00000." ); } /*TEST( FileNameTest, Extension ) -- GitLab From 904fa8a309044a2be267f2bb5ce4f4a28a668492 Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber Date: Tue, 6 Nov 2018 10:21:04 +0100 Subject: [PATCH 015/111] Added compilation of StringExample. --- src/Examples/CMakeLists.txt | 4 ++++ src/Examples/StringExample.cpp | 17 ++++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/Examples/CMakeLists.txt b/src/Examples/CMakeLists.txt index 8fcc4a5de..305020587 100644 --- a/src/Examples/CMakeLists.txt +++ b/src/Examples/CMakeLists.txt @@ -17,3 +17,7 @@ add_subdirectory( flow-vl ) #add_subdirectory( hamilton-jacobi-parallel-map ) #add_subdirectory( fast-sweeping-map ) #add_subdirectory( narrow-band ) + + +ADD_EXECUTABLE( StringExample StringExample.cpp ) +target_link_libraries( StringExample tnl ) \ No newline at end of file diff --git a/src/Examples/StringExample.cpp b/src/Examples/StringExample.cpp index f33da1392..d6c45dee8 100644 --- a/src/Examples/StringExample.cpp +++ b/src/Examples/StringExample.cpp @@ -1,8 +1,10 @@ #include +#include -using namespace TNL +using namespace TNL; +using namespace std; -int main() +int main( int argc, char* argv[] ) { // constructors String str1; @@ -16,23 +18,24 @@ int main() cout << "str4:" << str4 << endl; // functions - int size = str3.getSize(); + /*int size = str3.getSize(); cout << "size of string:" << size << "bytes" << endl; int alloc_size = str3.getAllocatedSize(); cout << "alloc_size:" << alloc_size << endl; - int memory = str1.setSize( 256 ); - cout << "memory:" << memory << endl; + str1.setSize( 256 ); + size = str3.getSize(); + cout << "size of string:" << size << "bytes" << endl;*/ String str setter = str.setString( "Something new" ); cout << "setter:" << setter << endl; - int getter = str4.getString(); + const char* getter = str4.getString(); cout << "getter:" << getter << endl; - String word( computer ) ; + String word( "computer" ) ; third_letter = word[2]; cout << "third_letter:" << third_letter << endl; -- GitLab From 5ce212fee3df93805dd68e5f4bfbdd377668fb45 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Tue, 6 Nov 2018 15:04:20 +0100 Subject: [PATCH 016/111] Added documentation for FileName. More FileNameTests. --- src/TNL/FileName.h | 32 +++++++++++++++++++++++++++----- src/TNL/String.h | 28 ++++++++++++++++++++++------ src/UnitTests/FileNameTest.cpp | 26 +++++++++++++------------- 3 files changed, 62 insertions(+), 24 deletions(-) diff --git a/src/TNL/FileName.h b/src/TNL/FileName.h index a9d301b0e..77b0b9db2 100644 --- a/src/TNL/FileName.h +++ b/src/TNL/FileName.h @@ -27,17 +27,39 @@ void removeFileExtension( String& file_name ); class FileName { public: - + + /// \brief Basic constructor. + /// + /// Constructs an empty filename object. FileName(); - + + /// \brief Sets the base name of given file. + /// + /// Sets \e fileNameBase as the base name of given file. + /// @param fileNameBase String that specifies new name of file. void setFileNameBase( const String& fileNameBase ); - + + /// \brief Sets the extension of given file. + /// + /// Sets \e extension as suffix of a file name. + /// @param extension String that specifies extension of file (without dot). Suffix of a file name. E.g. doc, xls, tnl. void setExtension( const String& extension ); - + + // \brief Sets index for given file. + /// + /// Sets \e index after the base name of given file. + /// @param index Integer - number of maximum 5(default) digits. (Number of digits can be changed with \c setDigitsCount). void setIndex( const int index ); - + + // \brief Sets number of digits for index of given file. + /// + /// @param digitsCount Integer - number of digits. void setDigitsCount( const int digitsCount ); + /// Creates appropriate name for given file. + /// + /// Creates particular file name using \e fileNameBase, \e digitsCount, + /// \e index and \e extension. String getFileName(); protected: diff --git a/src/TNL/String.h b/src/TNL/String.h index 5d9a3f003..b981c9df4 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -39,7 +39,7 @@ class String ///// /// \brief Basic constructor. /// - /// Constructs an empty string object with the length of zero characters. + /// Constructs an empty string object. String(); ///// @@ -88,17 +88,33 @@ class String /// Returns the number of characters in given string. Equivalent to getSize(). int getLength() const; - /// Returns the number of characters in given string. + /// \brief Returns the number of characters in given string. + /// + /// \par Example + /// \include StringExampleGetSize.cpp + /// \par Output + /// \include StringExampleGetSize.out int getSize() const; - /// Returns size of allocated storage for given string. + /// Returns size of allocated storage for given string. + /// + /// \par Example + /// \include StringExampleGetAllocatedSize.cpp + /// \par Output + /// \include StringExampleGetAllocatedSize.out int getAllocatedSize() const; ///// - /// Reserves space for given \e size. + /// \brief Reserves space for given \e size. + /// /// Requests to allocate storage space of given \e size to avoid memory reallocation. /// It allocates one more byte for the terminating 0. /// @param size Number of characters. + /// + /// \par Example + /// \include StringExampleSetSize.cpp + /// \par Output + /// \include StringExampleSetSize.out void setSize( int size ); ///// @@ -186,11 +202,11 @@ class String /// \brief This function overloads operator=(). /// - /// It assigns character /e str to this string. + /// It assigns character \e str to this string. String& operator=( char str ); /// \brief This function overloads operator+=(). /// - /// It appends character /e str to this string. + /// It appends character \e str to this string. String& operator+=( char str ); // This function concatenates strings and returns a newly constructed string object. String operator+( char str ) const; diff --git a/src/UnitTests/FileNameTest.cpp b/src/UnitTests/FileNameTest.cpp index 38192af05..8819b609c 100644 --- a/src/UnitTests/FileNameTest.cpp +++ b/src/UnitTests/FileNameTest.cpp @@ -24,7 +24,7 @@ TEST( FileNameTest, Constructor ) { FileName fname; - EXPECT_EQ( strcmp( fname.getFileName(), "00000." ), 0 ); + EXPECT_EQ( fname.getFileName(), "00000." ); } TEST( FileNameTest, Base ) @@ -32,34 +32,34 @@ TEST( FileNameTest, Base ) FileName fname; fname.setFileNameBase("name"); - EXPECT_EQ( strcmp( fname.getFileName(), "name00000." ), 0 ); + EXPECT_EQ( fname.getFileName(), "name00000." ); } -/*TEST( FileNameTest, Extension ) +TEST( FileNameTest, Extension ) { FileName fname; fname.setExtension("tnl"); - EXPECT_EQ( strcmp( fname.getFileName(), "00000.tnl" ), 0 ); -}*/ + EXPECT_EQ( fname.getFileName(), "00000.tnl" ); +} -/*TEST( FileNameTest, Index ) +TEST( FileNameTest, Index ) { FileName fname1; FileName fname2; fname1.setIndex(1); fname2.setIndex(50); - EXPECT_EQ( strcmp( fname1.getFileName(), "00001." ), 0 ); - EXPECT_EQ( strcmp( fname2.getFileName(), "00050." ), 0 ); -}*/ + EXPECT_EQ( fname1.getFileName(), "00001." ); + EXPECT_EQ( fname2.getFileName(), "00050." ); +} -/*TEST( FileNameTest, DigitsCount ) +TEST( FileNameTest, DigitsCount ) { FileName fname; fname.setDigitsCount(4); - EXPECT_EQ( strcmp( fname.getFileName(), "0000." ), 0 ); + EXPECT_EQ( fname.getFileName(), "0000." ); } TEST( FileNameTest, AllTogether ) @@ -70,8 +70,8 @@ TEST( FileNameTest, AllTogether ) fname.setIndex(8); fname.setDigitsCount(3); - EXPECT_EQ( strcmp( fname.getFileName(), "name008.tnl" ), 0 ); -}*/ + EXPECT_EQ( fname.getFileName(), "name008.tnl" ); +} #endif -- GitLab From c55ec589a1b3ab9de7af46415a3c20cb320cdda3 Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber Date: Tue, 6 Nov 2018 15:51:01 +0100 Subject: [PATCH 017/111] Fixed documentation in string. --- src/TNL/String.h | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/src/TNL/String.h b/src/TNL/String.h index 5d9a3f003..ed8df0a16 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -39,13 +39,12 @@ class String ///// /// \brief Basic constructor. /// - /// Constructs an empty string object with the length of zero characters. + /// Constructs an empty string object. String(); ///// /// \brief Constructor with char pointer. /// - /// Copies the null-terminated character sequence (C-string) pointed by \e c. /// Constructs a string initialized with the 8-bit string \e c, excluding /// the given number of \e prefix_cut_off and \e sufix_cut_off characters. /// @@ -74,6 +73,7 @@ class String /// \brief Converts anything to a string. /// /// This function converts any type of value into type string. + /// @tparam T is a type of a value to be converted /// @param value Word of any type (e.g. int, bool, double,...). template< typename T > String( T value ) @@ -85,13 +85,13 @@ class String /// \brief Destructor. ~String(); - /// Returns the number of characters in given string. Equivalent to getSize(). + /// \brief Returns the number of characters in given string. Equivalent to getSize(). int getLength() const; - /// Returns the number of characters in given string. + /// \brief Returns the number of characters in given string. int getSize() const; - /// Returns size of allocated storage for given string. + /// \brief Returns size of allocated storage for given string. int getAllocatedSize() const; ///// @@ -115,25 +115,23 @@ class String ///// /// \brief Returns pointer to data. /// - /// It returns the content of the given string. The content can not be - /// changed by user. + /// It returns the content of the given string as a constant pointer to char. const char* getString() const; /// \brief Returns pointer to data. /// - /// It returns the content of the given string. The content can be changed - /// by user. + /// It returns the content of the given string as a non-constant pointer to char. char* getString(); ///// - /// \brief Operator for accesing particular chars of the string. + /// \brief Operator for accessing particular chars of the string. /// /// This function overloads operator[](). It returns a reference to /// the character at position \e i in given string. /// The character can not be changed be user. const char& operator[]( int i ) const; - /// \brief Operator for accesing particular chars of the string. + /// \brief Operator for accessing particular chars of the string. /// /// It returns the character at the position \e i in given string as /// a modifiable reference. @@ -244,23 +242,17 @@ class String ///// /// \brief Function for saving file. /// - /// Writes to a binary file and returns boolean expression based on the + /// Writes the string to a binary file and returns boolean expression based on the /// success in writing into the file. bool save( File& file ) const; ///// /// \brief Function for loading from file. /// - /// Reads from binary file and returns boolean expression based on the + /// Reads a string from binary file and returns boolean expression based on the /// success in reading the file. bool load( File& file ); - - // !!! Mozem dat prec??? - // Broadcast to other nodes in MPI cluster - // void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); - - ///// /// \brief Function for getting a line from stream. /// @@ -268,11 +260,11 @@ class String /// expression based on the success in reading the line. bool getLine( std::istream& stream ); - ///toto neviem co friend std::ostream& operator<<( std::ostream& stream, const String& str ); protected: - /// Pointer to char ended with zero ...Preco? + + /// Pointer to char ended with zero byte char* string; /// Length of allocated piece of memory. @@ -286,7 +278,7 @@ String operator+( char string1, const String& string2 ); /// Returns concatenation of \e string1 and \e string2. String operator+( const char* string1, const String& string2 ); -/// Toto neviem co +/// Performs the string output to a stream std::ostream& operator<<( std::ostream& stream, const String& str ); template< typename T > -- GitLab From f9f90d8e701a7871f5a99aa373ed57e078df56ff Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Thu, 8 Nov 2018 13:12:39 +0100 Subject: [PATCH 018/111] Documentation of Timer. --- src/Examples/StringExample.out | 2 +- src/TNL/FileName.h | 14 ++++++----- src/TNL/Timer.h | 46 +++++++++++++++++++++++++++++++--- src/UnitTests/FileNameTest.cpp | 3 ++- 4 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/Examples/StringExample.out b/src/Examples/StringExample.out index 87170b8a9..61886792a 100644 --- a/src/Examples/StringExample.out +++ b/src/Examples/StringExample.out @@ -5,7 +5,7 @@ str3: string str4: 28.4 //string type //functions -size of string: 6 bytes +size of string: 8 bytes alloc_size: 256 memory: 512 setter: Something new diff --git a/src/TNL/FileName.h b/src/TNL/FileName.h index 77b0b9db2..d12e82835 100644 --- a/src/TNL/FileName.h +++ b/src/TNL/FileName.h @@ -40,24 +40,26 @@ class FileName void setFileNameBase( const String& fileNameBase ); /// \brief Sets the extension of given file. - /// + /// /// Sets \e extension as suffix of a file name. - /// @param extension String that specifies extension of file (without dot). Suffix of a file name. E.g. doc, xls, tnl. + /// @param extension String that specifies extension of file (without dot). + /// Suffix of a file name. E.g. doc, xls, tnl. void setExtension( const String& extension ); - // \brief Sets index for given file. + /// \brief Sets index for given file. /// /// Sets \e index after the base name of given file. - /// @param index Integer - number of maximum 5(default) digits. (Number of digits can be changed with \c setDigitsCount). + /// @param index Integer - number of maximum 5(default) digits. + /// (Number of digits can be changed with \c setDigitsCount). void setIndex( const int index ); - // \brief Sets number of digits for index of given file. + /// \brief Sets number of digits for index of given file. /// /// @param digitsCount Integer - number of digits. void setDigitsCount( const int digitsCount ); /// Creates appropriate name for given file. - /// + /// /// Creates particular file name using \e fileNameBase, \e digitsCount, /// \e index and \e extension. String getFileName(); diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index f885bdd44..13567a438 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -15,32 +15,67 @@ namespace TNL { class Logger; +/// \brief Class for time measuring class Timer { public: - + + ///// + /// \brief Basic constructor. + /// + /// This function creates a new timer. Timer(); + ///// + /// \brief Resets timer. + /// + /// Resets all time and cycle measurements such as real time, CPU time and CPU cycles. + /// Sets all of them to zero. void reset(); + //// + /// \brief Stops timer. + /// + /// Stops all time and cycle measurements such as real time, CPU time and CPU cycles. void stop(); + ///// + /// \brief Starts timer. + /// + /// Starts all time and cycle measurements such as real time, CPU time and CPU cycles. void start(); + /// \brief Counts the real (clock) time starting after the function \c start() is called. double getRealTime() const; + ///// + /// \brief Measures the CPU time. + /// + /// CPU time is the time that measures how long it takes processor + /// to complete all computations. double getCPUTime() const; + /// Counts the number of CPU cycles (machine cycles). unsigned long long int getCPUCycles() const; - + + /// \brief Writes a record to the \e logger. + /// + /// \param logger + /// \param logLevel bool writeLog( Logger& logger, int logLevel = 0 ) const; protected: - + + /// Function for reading the real time from timer. double readRealTime() const; + /// \brief Function for reading the CPU time from timer. + /// + /// CPU time is the time that measures how long it takes processor + /// to complete all computations. double readCPUTime() const; + /// \brief Function for reading the number of CPU cycles (machine cycles). unsigned long long int readCPUCycles() const; @@ -48,7 +83,10 @@ class Timer initialCPUTime, totalCPUTime; unsigned long long int initialCPUCycles, totalCPUCycles; - + + /// \brief Saves information about state of the timer. + /// + /// Knows whether the timer is currently stopped or not. bool stopState; inline unsigned long long rdtsc() const diff --git a/src/UnitTests/FileNameTest.cpp b/src/UnitTests/FileNameTest.cpp index 8819b609c..5a69a1f28 100644 --- a/src/UnitTests/FileNameTest.cpp +++ b/src/UnitTests/FileNameTest.cpp @@ -15,7 +15,7 @@ #endif #include -#include +// #include using namespace TNL; @@ -71,6 +71,7 @@ TEST( FileNameTest, AllTogether ) fname.setDigitsCount(3); EXPECT_EQ( fname.getFileName(), "name008.tnl" ); + EXPECT_EQ( getFileExtension(fname.getFileName()), "tnl" ); } #endif -- GitLab From e39add58b16fbfe8260632ce621c8a528821bfc7 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Fri, 9 Nov 2018 15:12:37 +0100 Subject: [PATCH 019/111] Started documentation of File. --- src/TNL/File.h | 15 ++++++++++++--- src/TNL/Timer.h | 6 +++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/TNL/File.h b/src/TNL/File.h index 7a8a024db..8ccfe90b1 100644 --- a/src/TNL/File.h +++ b/src/TNL/File.h @@ -36,9 +36,8 @@ enum class IOMode */ const size_t FileGPUvsCPUTransferBufferSize = 5 * 2<<20; -/* - * This file is aimed mainly for the binary data. It supports transparent compression. - */ + +/// Class file is aimed mainly for the binary data. It supports transparent compression. class File { IOMode mode; @@ -55,10 +54,19 @@ class File public: + /// Basic constructor. File(); + /// Destructor. ~File(); + ///// + /// \brief Opens given file. + /// + /// Opens file with given \e fileName and returns true/false based on the success in opening the file. + /// \param fileName String which indicates name of the file user wants to open. + /// \param mode Indicates what user needs to do with opened file. + /// Modes to choose: IOMode::read or IOMode::write. bool open( const String& fileName, const IOMode mode ); @@ -92,6 +100,7 @@ class File template< typename Type, typename Device = Devices::Host > bool write( const Type* buffer ); + /// \brief Closes given file and returns true/false based on the success in closing the file. bool close(); protected: diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index 13567a438..a0bd36ae8 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -66,10 +66,10 @@ class Timer protected: - /// Function for reading the real time from timer. + /// Function for reading the real time. double readRealTime() const; - /// \brief Function for reading the CPU time from timer. + /// \brief Function for reading the CPU time. /// /// CPU time is the time that measures how long it takes processor /// to complete all computations. @@ -84,7 +84,7 @@ class Timer unsigned long long int initialCPUCycles, totalCPUCycles; - /// \brief Saves information about state of the timer. + /// \brief Saves information about state of the timer. /// /// Knows whether the timer is currently stopped or not. bool stopState; -- GitLab From bb08caf65290e35d32fbd02e9f1c42705b18f3ba Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Tue, 13 Nov 2018 09:49:24 +0100 Subject: [PATCH 020/111] Added String examples. --- src/Examples/StringExampleGetAllocatedSize.cpp | 10 ++++++++++ src/Examples/StringExampleGetSize.cpp | 11 +++++++++++ src/Examples/StringExampleSetSize.cpp | 10 ++++++++++ 3 files changed, 31 insertions(+) create mode 100644 src/Examples/StringExampleGetAllocatedSize.cpp create mode 100644 src/Examples/StringExampleGetSize.cpp create mode 100644 src/Examples/StringExampleSetSize.cpp diff --git a/src/Examples/StringExampleGetAllocatedSize.cpp b/src/Examples/StringExampleGetAllocatedSize.cpp new file mode 100644 index 000000000..993ad3df4 --- /dev/null +++ b/src/Examples/StringExampleGetAllocatedSize.cpp @@ -0,0 +1,10 @@ +#include + +using namespace TNL + +int main() +{ + String str("my world") + int alloc_size = str.getAllocatedSize(); + cout << "alloc_size:" << alloc_size << endl; +} \ No newline at end of file diff --git a/src/Examples/StringExampleGetSize.cpp b/src/Examples/StringExampleGetSize.cpp new file mode 100644 index 000000000..b2c30f63a --- /dev/null +++ b/src/Examples/StringExampleGetSize.cpp @@ -0,0 +1,11 @@ +#include + +using namespace TNL + +int main() +{ + String str("my world") + int size = str.getSize(); + cout << "size of string:" << size << "bytes" << endl; +} + diff --git a/src/Examples/StringExampleSetSize.cpp b/src/Examples/StringExampleSetSize.cpp new file mode 100644 index 000000000..2e53f88b6 --- /dev/null +++ b/src/Examples/StringExampleSetSize.cpp @@ -0,0 +1,10 @@ +#include + +using namespace TNL + +int main() +{ + int memory + memory.setSize( 256 ); + cout << "memory:" << memory << endl; +} -- GitLab From 63b5f538473e6d618168d7b26e8c6a6e769ff7fd Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Tue, 13 Nov 2018 09:50:04 +0100 Subject: [PATCH 021/111] Added unit tests for Timer. --- src/UnitTests/TimerTest.cpp | 45 +++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/UnitTests/TimerTest.cpp diff --git a/src/UnitTests/TimerTest.cpp b/src/UnitTests/TimerTest.cpp new file mode 100644 index 000000000..16acbbd21 --- /dev/null +++ b/src/UnitTests/TimerTest.cpp @@ -0,0 +1,45 @@ +/*************************************************************************** + FileNameTest.cpp - description + ------------------- + begin : Oct 17, 2018 + copyright : (C) 2018 by Tomas Oberhuber + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by Nina Dzugasova + +#ifdef HAVE_GTEST +#include +#endif + +#include + +using namespace TNL; + +#ifdef HAVE_GTEST +TEST( TimerTest, Constructor ) +{ + Timer time; + time.reset(); + EXPECT_EQ(time.getRealTime(),0); + time.start(); + time.stop(); + EXPECT_NE(time.getRealTime(),0); +} +#endif + + +#include "GtestMissingError.h" +int main( int argc, char* argv[] ) +{ +#ifdef HAVE_GTEST + ::testing::InitGoogleTest( &argc, argv ); + return RUN_ALL_TESTS(); +#else + throw GtestMissingError(); +#endif +} + + -- GitLab From 9fd72de06c9140c070d34f340e6a08c8dc552054 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Tue, 13 Nov 2018 09:51:11 +0100 Subject: [PATCH 022/111] Starting with documentation of File. --- src/TNL/File.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TNL/File.h b/src/TNL/File.h index 8ccfe90b1..8f8d13ee6 100644 --- a/src/TNL/File.h +++ b/src/TNL/File.h @@ -61,7 +61,7 @@ class File ~File(); ///// - /// \brief Opens given file. + /// \brief Opens given file. /// /// Opens file with given \e fileName and returns true/false based on the success in opening the file. /// \param fileName String which indicates name of the file user wants to open. -- GitLab From 03002e722d82d736778eec7b03c3d9785f948ce5 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Tue, 13 Nov 2018 15:03:20 +0100 Subject: [PATCH 023/111] Better documentation of Timer. --- src/TNL/Timer.h | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index a0bd36ae8..ecbba35d4 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -23,7 +23,7 @@ class Timer ///// /// \brief Basic constructor. /// - /// This function creates a new timer. + /// This function creates a new timer and resets it. Timer(); ///// @@ -34,48 +34,60 @@ class Timer void reset(); //// - /// \brief Stops timer. + /// \brief Stops (pauses) the timer. /// - /// Stops all time and cycle measurements such as real time, CPU time and CPU cycles. + /// Pauses all time and cycle measurements such as real time, CPU time and + /// CPU cycles, but does not set them to zero. void stop(); ///// /// \brief Starts timer. /// - /// Starts all time and cycle measurements such as real time, CPU time and CPU cycles. + /// Starts all time and cycle measurements such as real time, CPU time and + /// CPU cycles. Function start() can be used also after using stop() function. + /// The timer then continues measuring the time without reseting. void start(); - /// \brief Counts the real (clock) time starting after the function \c start() is called. + /// \brief Returs the real (clock/timer) time. + /// + /// It returns the elapsed time between calling the start() and stop() functions. + /// Starts counting the real time after the function start() is called and + /// pauses when the function stop() is called. + /// If the timer have been started more then one time without resetting, + /// the real time is counted by adding all intervals (between start and stop + /// functions) together. + /// This function can be called while the timer is running, there is no + /// need to use stop() function first. double getRealTime() const; ///// - /// \brief Measures the CPU time. + /// \brief Returns the CPU time. /// /// CPU time is the time that measures how long it takes processor /// to complete all computations. double getCPUTime() const; - /// Counts the number of CPU cycles (machine cycles). + /// Returns the number of CPU cycles (machine cycles). unsigned long long int getCPUCycles() const; /// \brief Writes a record to the \e logger. /// /// \param logger - /// \param logLevel + /// \param logLevel A whole number from zero up, which indicates the indent. bool writeLog( Logger& logger, int logLevel = 0 ) const; protected: - /// Function for reading the real time. + /// Function for measuring the real time. double readRealTime() const; - /// \brief Function for reading the CPU time. + /// \brief Function for measuring the CPU time. /// /// CPU time is the time that measures how long it takes processor /// to complete all computations. double readCPUTime() const; - /// \brief Function for reading the number of CPU cycles (machine cycles). + /// \brief Function for counting the number of CPU cycles (machine cycles). unsigned long long int readCPUCycles() const; -- GitLab From d3a4c896328212e555ac06238a441af9037a69ee Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Tue, 13 Nov 2018 15:37:06 +0100 Subject: [PATCH 024/111] Added documentation of File. --- src/TNL/File.h | 14 +++++++++++--- src/TNL/Timer.h | 6 +++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/TNL/File.h b/src/TNL/File.h index 8f8d13ee6..029246647 100644 --- a/src/TNL/File.h +++ b/src/TNL/File.h @@ -37,7 +37,7 @@ enum class IOMode const size_t FileGPUvsCPUTransferBufferSize = 5 * 2<<20; -/// Class file is aimed mainly for the binary data. It supports transparent compression. +/// Class file is aimed mainly for the binary data. class File { IOMode mode; @@ -66,21 +66,23 @@ class File /// Opens file with given \e fileName and returns true/false based on the success in opening the file. /// \param fileName String which indicates name of the file user wants to open. /// \param mode Indicates what user needs to do with opened file. - /// Modes to choose: IOMode::read or IOMode::write. + /// Modes to choose: IOMode::read or IOMode::write or IOMode::undefined. bool open( const String& fileName, const IOMode mode ); - + /// \brief Returns name of given file. const String& getFileName() const { return this->fileName; } + /// Returns read elements. long int getReadElements() const { return this->readElements; } + /// Returns written elements. long int getWrittenElements() const { return this->writtenElements; @@ -90,6 +92,7 @@ class File bool read( Type* buffer, const Index& elements ); + // Toto je treba?? template< typename Type, typename Device = Devices::Host > bool read( Type* buffer ); @@ -97,6 +100,7 @@ class File bool write( const Type* buffer, const Index elements ); + // Toto je treba? template< typename Type, typename Device = Devices::Host > bool write( const Type* buffer ); @@ -147,6 +151,10 @@ protected: const std::size_t& elements ); }; +/// Returns true if the file exists and false otherwise. +/// +/// Finds out if the file \e fileName exists. +/// \param fileName Name of the file that user wants to find in the PC. bool fileExists( const String& fileName ); } // namespace TNL diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index ecbba35d4..8bf31c192 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -100,7 +100,10 @@ class Timer /// /// Knows whether the timer is currently stopped or not. bool stopState; - + + /// \brief Time Stamp Counter returning number of CPU cycles since reset. + /// + /// Only for x86 compatibile CPUs. inline unsigned long long rdtsc() const { unsigned hi, lo; @@ -109,6 +112,7 @@ class Timer } }; +// !!! Odstranit ???!!! extern Timer defaultTimer; } // namespace TNL -- GitLab From fda825f6e167c648a81cc3efd34670bf3fd07f6e Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Wed, 14 Nov 2018 12:02:28 +0100 Subject: [PATCH 025/111] Added documentation into file. --- src/TNL/File.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/TNL/File.h b/src/TNL/File.h index 029246647..8e0836b35 100644 --- a/src/TNL/File.h +++ b/src/TNL/File.h @@ -88,6 +88,11 @@ class File return this->writtenElements; } + /// \brief Function that gets elements from given file. + /// + /// Returns boolean value based on the succes in reading elements from given file. + /// \param buffer Pointer in memory. + /// \param elements Number of elements the user wants to get (read) from given file. template< typename Type, typename Device = Devices::Host, typename Index = int > bool read( Type* buffer, const Index& elements ); @@ -96,6 +101,11 @@ class File template< typename Type, typename Device = Devices::Host > bool read( Type* buffer ); + /// \brief Function that writes elements into given file. + /// + /// Returns boolean value based on the succes in writing elements into given file. + /// \param buffer Pointer in memory. + /// \param elements Number of elements the user wants to write into the given file. template< typename Type, typename Device = Devices::Host, typename Index = int > bool write( const Type* buffer, const Index elements ); -- GitLab From 525479637b9e10807d6671cac1520a5d35cd4d6b Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Wed, 14 Nov 2018 14:59:25 +0100 Subject: [PATCH 026/111] Added documentation to Logger. --- src/TNL/File.h | 4 ++-- src/TNL/Logger.h | 15 ++++++++++++++- src/TNL/Timer.h | 6 +++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/TNL/File.h b/src/TNL/File.h index 8e0836b35..b690d610c 100644 --- a/src/TNL/File.h +++ b/src/TNL/File.h @@ -88,7 +88,7 @@ class File return this->writtenElements; } - /// \brief Function that gets elements from given file. + /// \brief Method that can write particular data type from given file into GPU. (Function that gets particular elements from given file.) /// /// Returns boolean value based on the succes in reading elements from given file. /// \param buffer Pointer in memory. @@ -101,7 +101,7 @@ class File template< typename Type, typename Device = Devices::Host > bool read( Type* buffer ); - /// \brief Function that writes elements into given file. + /// \brief Method that can write particular data type from CPU into given file. (Function that writes particular elements into given file.) /// /// Returns boolean value based on the succes in writing elements into given file. /// \param buffer Pointer in memory. diff --git a/src/TNL/Logger.h b/src/TNL/Logger.h index 5b7fda238..c6e672d4f 100644 --- a/src/TNL/Logger.h +++ b/src/TNL/Logger.h @@ -19,16 +19,29 @@ class Logger { public: + /// \brief Basic constructor. + /// + /// \param _width Integer that defines the width of logger. + /// \param _stream Where to create the logger, e.g. cout or a certain file.s Logger( int _width, std::ostream& _stream ); + /// \brief Creates header in given logger. + /// + /// \param title String desribing the title/header. void writeHeader( const String& title ); + /// \brief Creates predefined separator - structure in the logger. void writeSeparator(); + /// \brief Inserts information about system parameters into logger. + /// + /// \param parameters bool writeSystemInformation( const Config::ParameterContainer& parameters ); - + /// \brief Inserts a line with current time into logger. + /// + /// \param label Description of the current time line. void writeCurrentTime( const char* label ); // TODO: add units diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index 8bf31c192..3d40bc485 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -53,7 +53,7 @@ class Timer /// It returns the elapsed time between calling the start() and stop() functions. /// Starts counting the real time after the function start() is called and /// pauses when the function stop() is called. - /// If the timer have been started more then one time without resetting, + /// If the timer have been started more then once without resetting, /// the real time is counted by adding all intervals (between start and stop /// functions) together. /// This function can be called while the timer is running, there is no @@ -70,7 +70,7 @@ class Timer /// Returns the number of CPU cycles (machine cycles). unsigned long long int getCPUCycles() const; - /// \brief Writes a record to the \e logger. + /// \brief Writes a record into the \e logger. /// /// \param logger /// \param logLevel A whole number from zero up, which indicates the indent. @@ -96,7 +96,7 @@ class Timer unsigned long long int initialCPUCycles, totalCPUCycles; - /// \brief Saves information about state of the timer. + /// \brief Saves information about the state of given timer. /// /// Knows whether the timer is currently stopped or not. bool stopState; -- GitLab From 4e387085dccfa9601199cad7d70817b8516c7bea Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Thu, 15 Nov 2018 14:14:03 +0100 Subject: [PATCH 027/111] Added documentation into Containers/List. --- src/TNL/Containers/List.h | 63 ++++++++++++++++++++++--------------- src/TNL/File.h | 4 +-- src/TNL/Logger.h | 5 ++- src/UnitTests/TimerTest.cpp | 8 +++-- 4 files changed, 50 insertions(+), 30 deletions(-) diff --git a/src/TNL/Containers/List.h b/src/TNL/Containers/List.h index c64a8a957..2f53ccd8c 100644 --- a/src/TNL/Containers/List.h +++ b/src/TNL/Containers/List.h @@ -43,27 +43,34 @@ template< class T > class List public: typedef T ValueType; - //! Basic constructor + /// \brief Basic constructor. + /// + /// Constructs an empty list. List(); - //! Copy constructor + /// \brief Copy constructor. + /// + /// Construct a copy of \e list. + /// @param list Name of another list. List( const List& list ); - //! Destructor + /// \brief Destructor. + /// + /// Destroys the list. References to the values in the list become invalid. ~List(); static String getType(); - //! If the list is empty return 'true' + /// Returns \e true if the list contains no items, otherwise returns \e false. bool isEmpty() const; - //! Return size of the list + /// Returns number of items in the list. int getSize() const; - //! Indexing operator + /// Indexing operator. T& operator[] ( const int& ind ); - //! Indexing operator for constant instances + /// Indexing operator for constant instances. const T& operator[] ( const int& ind ) const; const List& operator = ( const List& lst ); @@ -72,64 +79,70 @@ template< class T > class List bool operator != ( const List& lst ) const; - //! Append new data element + /// \brief Appends new data element. + /// + /// Inserts \e data at the end of the list. bool Append( const T& data ); - //! Prepend new data element + /// \brief Prepends new data element. + /// + /// Inserts \e data at the beginning of the list. bool Prepend( const T& data ); - //! Insert new data element at given position + /// \brief Inserts new data element at given position. + /// + /// Inserts \e data at index position \e ind in the list. bool Insert( const T& data, const int& ind ); - //! Append copy of another list + /// Appends copy of another list. bool AppendList( const List< T >& lst ); - //! Prepend copy of another list + /// Prepends copy of another list. bool PrependList( const List< T >& lst ); template< typename Array > void toArray( Array& array ); - //! Erase data element at given position + /// Erases data element at given position. void Erase( const int& ind ); - //! Erase data element with contained data at given position + /// Erases data element with contained data at given position. void DeepErase( const int& ind ); - //! Erase all data elements + /// Erases all data elements. void reset(); - //! Erase all data elements with contained data + /// Erases all data elements with contained data. void DeepEraseAll(); - //! Save the list in binary format + /// Saves the list in binary format. bool Save( File& file ) const; - //! Save the list in binary format using method save of type T + /// Saves the list in binary format using method save of type T. bool DeepSave( File& file ) const; - //! Load the list + /// Loads the list. bool Load( File& file ); - //! Load the list using method Load of the type T + /// Loads the list using method Load of the type T. bool DeepLoad( File& file ); protected: - //! Pointer to the first element + /// Pointer to the first element. ListDataElement< T >* first; - //! Pointer to the last element + /// Pointer to the last element. /*! We use pointer to last element while adding new element to keep order of elements */ ListDataElement< T >* last; - //! List size + /// List size. int size; - //! Iterator + /// Iterator. mutable ListDataElement< T >* iterator; - //! Iterator index + /// Iterator index. mutable int index; }; diff --git a/src/TNL/File.h b/src/TNL/File.h index b690d610c..c156113f0 100644 --- a/src/TNL/File.h +++ b/src/TNL/File.h @@ -76,13 +76,13 @@ class File return this->fileName; } - /// Returns read elements. + /// Returns number of read elements. long int getReadElements() const { return this->readElements; } - /// Returns written elements. + /// Returns number of written elements. long int getWrittenElements() const { return this->writtenElements; diff --git a/src/TNL/Logger.h b/src/TNL/Logger.h index c6e672d4f..87298f9e4 100644 --- a/src/TNL/Logger.h +++ b/src/TNL/Logger.h @@ -19,6 +19,7 @@ class Logger { public: + ///// /// \brief Basic constructor. /// /// \param _width Integer that defines the width of logger. @@ -26,6 +27,7 @@ class Logger Logger( int _width, std::ostream& _stream ); + ///// /// \brief Creates header in given logger. /// /// \param title String desribing the title/header. @@ -34,11 +36,12 @@ class Logger /// \brief Creates predefined separator - structure in the logger. void writeSeparator(); - /// \brief Inserts information about system parameters into logger. + /// \brief Inserts information about various system parameters into logger. /// /// \param parameters bool writeSystemInformation( const Config::ParameterContainer& parameters ); + ///// /// \brief Inserts a line with current time into logger. /// /// \param label Description of the current time line. diff --git a/src/UnitTests/TimerTest.cpp b/src/UnitTests/TimerTest.cpp index 16acbbd21..6c20c4abb 100644 --- a/src/UnitTests/TimerTest.cpp +++ b/src/UnitTests/TimerTest.cpp @@ -24,9 +24,13 @@ TEST( TimerTest, Constructor ) Timer time; time.reset(); EXPECT_EQ(time.getRealTime(),0); - time.start(); + /*time.start(); + EXPECT_FALSE(time.stopState); + time.stop(); - EXPECT_NE(time.getRealTime(),0); + EXPECT_TRUE(time.stopState); + + EXPECT_NE(time.getRealTime(),0);*/ } #endif -- GitLab From 01221b2f0a95b5a7c05dcc6942cc719232a31807 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 19 Nov 2018 15:44:10 +0100 Subject: [PATCH 028/111] Only small adjustments. --- src/TNL/Containers/List.h | 4 +++- src/TNL/File.h | 7 ++++++- src/TNL/Logger.h | 2 +- src/TNL/Timer.h | 16 ++++++++++++---- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/TNL/Containers/List.h b/src/TNL/Containers/List.h index 2f53ccd8c..3954b014e 100644 --- a/src/TNL/Containers/List.h +++ b/src/TNL/Containers/List.h @@ -112,7 +112,9 @@ template< class T > class List /// Erases all data elements. void reset(); - /// Erases all data elements with contained data. + /// \brief Erases all data elements with contained data. + /// + /// Frees dynamicaly allocated data inside the data elements void DeepEraseAll(); /// Saves the list in binary format. diff --git a/src/TNL/File.h b/src/TNL/File.h index c156113f0..c6f55ff76 100644 --- a/src/TNL/File.h +++ b/src/TNL/File.h @@ -38,6 +38,11 @@ const size_t FileGPUvsCPUTransferBufferSize = 5 * 2<<20; /// Class file is aimed mainly for the binary data. +/// +/// \par Example +/// \include FileExample.cpp +// \par Output +// \include FileExample.out class File { IOMode mode; @@ -91,7 +96,7 @@ class File /// \brief Method that can write particular data type from given file into GPU. (Function that gets particular elements from given file.) /// /// Returns boolean value based on the succes in reading elements from given file. - /// \param buffer Pointer in memory. + /// \param buffer Pointer in memory (where the read elements are stored?). /// \param elements Number of elements the user wants to get (read) from given file. template< typename Type, typename Device = Devices::Host, typename Index = int > bool read( Type* buffer, diff --git a/src/TNL/Logger.h b/src/TNL/Logger.h index 87298f9e4..10ecf800c 100644 --- a/src/TNL/Logger.h +++ b/src/TNL/Logger.h @@ -23,7 +23,7 @@ class Logger /// \brief Basic constructor. /// /// \param _width Integer that defines the width of logger. - /// \param _stream Where to create the logger, e.g. cout or a certain file.s + /// \param _stream Where to create the logger, e.g. cout or a certain files. Logger( int _width, std::ostream& _stream ); diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index 3d40bc485..1ccc27537 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -15,7 +15,12 @@ namespace TNL { class Logger; -/// \brief Class for time measuring +/// \brief Class for time measuring. +/// +/// \par Example +/// \include TimerExample.cpp +// \par Output +// \include TimerExample.out class Timer { public: @@ -48,7 +53,8 @@ class Timer /// The timer then continues measuring the time without reseting. void start(); - /// \brief Returs the real (clock/timer) time. + ///// + /// \brief Returs the elapsed time on given timer. /// /// It returns the elapsed time between calling the start() and stop() functions. /// Starts counting the real time after the function start() is called and @@ -61,7 +67,7 @@ class Timer double getRealTime() const; ///// - /// \brief Returns the CPU time. + /// \brief Returns the elapsed CPU time on given timer. /// /// CPU time is the time that measures how long it takes processor /// to complete all computations. @@ -78,7 +84,9 @@ class Timer protected: - /// Function for measuring the real time. + /// \brief Function for measuring the real time. + /// + /// Returns the current calendar time. double readRealTime() const; /// \brief Function for measuring the CPU time. -- GitLab From dc2a674190fa61b685ca76eaee309794221a71c8 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Tue, 20 Nov 2018 10:23:45 +0100 Subject: [PATCH 029/111] Added examples for File and Timer. --- src/Examples/FileExample.cpp | 25 +++++++++++++++++++++++++ src/Examples/TimerExample.cpp | 15 +++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/Examples/FileExample.cpp create mode 100644 src/Examples/TimerExample.cpp diff --git a/src/Examples/FileExample.cpp b/src/Examples/FileExample.cpp new file mode 100644 index 000000000..e0e81ab91 --- /dev/null +++ b/src/Examples/FileExample.cpp @@ -0,0 +1,25 @@ +#include +#include +#include + +using namespace TNL; +using namespace std; + +int main() +{ + File file; + + file.open( String("new-file.tnl"), IOMode::write ); + String title("Header"); + file.write( title ); + file.close(); + + file.open( String("new-file.tnl"), IOMode::read ); + String title2; + file.read( title2, 4); + file.close(); + + if fileExists( "new-file.tnl" ) + std::remove( "new-file.tnl" ); +} + diff --git a/src/Examples/TimerExample.cpp b/src/Examples/TimerExample.cpp new file mode 100644 index 000000000..772c9907b --- /dev/null +++ b/src/Examples/TimerExample.cpp @@ -0,0 +1,15 @@ +#include +#include + +using namespace TNL; +using namespace std; + +int main() +{ + Timer time; + time.start(); + time.stop(); + time.getRealTime(); + time.reset(); +} + -- GitLab From eb1c40d95428174a8ea8fcd075c933aecc76c67b Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber Date: Tue, 20 Nov 2018 13:18:55 +0100 Subject: [PATCH 030/111] Fixing documentation. --- src/Examples/CMakeLists.txt | 7 ++++++- src/TNL/File.h | 2 +- src/TNL/Logger.h | 27 +++++++++++++++------------ src/TNL/Logger_impl.h | 16 ++++++++-------- src/TNL/Timer.h | 2 +- 5 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/Examples/CMakeLists.txt b/src/Examples/CMakeLists.txt index 305020587..b8e7c574a 100644 --- a/src/Examples/CMakeLists.txt +++ b/src/Examples/CMakeLists.txt @@ -18,6 +18,11 @@ add_subdirectory( flow-vl ) #add_subdirectory( fast-sweeping-map ) #add_subdirectory( narrow-band ) +ADD_EXECUTABLE( FileExample FileExample.cpp ) +target_link_libraries( FileExample tnl ) ADD_EXECUTABLE( StringExample StringExample.cpp ) -target_link_libraries( StringExample tnl ) \ No newline at end of file +target_link_libraries( StringExample tnl ) + +ADD_EXECUTABLE( TimerExample TimerExample.cpp ) +target_link_libraries( TimerExample tnl ) \ No newline at end of file diff --git a/src/TNL/File.h b/src/TNL/File.h index c6f55ff76..bb31cdcd2 100644 --- a/src/TNL/File.h +++ b/src/TNL/File.h @@ -37,7 +37,7 @@ enum class IOMode const size_t FileGPUvsCPUTransferBufferSize = 5 * 2<<20; -/// Class file is aimed mainly for the binary data. +///\brief Class file is aimed mainly for the binary data. /// /// \par Example /// \include FileExample.cpp diff --git a/src/TNL/Logger.h b/src/TNL/Logger.h index 10ecf800c..bddcfeeeb 100644 --- a/src/TNL/Logger.h +++ b/src/TNL/Logger.h @@ -15,6 +15,7 @@ namespace TNL { +/// Vytvari tabulku s logem vypoctu class Logger { public: @@ -22,41 +23,43 @@ class Logger ///// /// \brief Basic constructor. /// - /// \param _width Integer that defines the width of logger. - /// \param _stream Where to create the logger, e.g. cout or a certain files. + /// \param _width Integer that defines the width of the log. + /// \param _stream Defines output stream where the log will be printed out. Logger( int _width, std::ostream& _stream ); ///// - /// \brief Creates header in given logger. + /// \brief Creates header in given log. + /// + /// The header usually contains title of the program. /// - /// \param title String desribing the title/header. + /// \param title String containing the header title. void writeHeader( const String& title ); - /// \brief Creates predefined separator - structure in the logger. + /// \brief Creates separator for structuring the log. void writeSeparator(); - /// \brief Inserts information about various system parameters into logger. + /// \brief Inserts information about various system parameters into the log. /// - /// \param parameters + /// \param parameters is a container with configuration parameters bool writeSystemInformation( const Config::ParameterContainer& parameters ); ///// - /// \brief Inserts a line with current time into logger. + /// \brief Inserts a line with current time into the log. /// - /// \param label Description of the current time line. + /// \param label Label to be printed to the log together with the current time. void writeCurrentTime( const char* label ); // TODO: add units - template< typename T > + template< typename ParameterType > void writeParameter( const String& label, const String& parameterName, const Config::ParameterContainer& parameters, int parameterLevel = 0 ); - template< typename T > + template< typename ParameterType > void writeParameter( const String& label, - const T& value, + const ParameterType& value, int parameterLevel = 0 ); protected: diff --git a/src/TNL/Logger_impl.h b/src/TNL/Logger_impl.h index c633b1743..08181070f 100644 --- a/src/TNL/Logger_impl.h +++ b/src/TNL/Logger_impl.h @@ -15,27 +15,27 @@ namespace TNL { -template< typename T > +template< typename ParameterType > void Logger::writeParameter( const String& label, - const String& parameterName, - const Config::ParameterContainer& parameters, - int parameterLevel ) + const String& parameterName, + const Config::ParameterContainer& parameters, + int parameterLevel ) { stream << "| "; int i; for( i = 0; i < parameterLevel; i ++ ) stream << " "; std::stringstream str; - str << parameters.getParameter< T >( parameterName ); + str << parameters.getParameter< ParameterType >( parameterName ); stream << label << std::setw( width - label.getLength() - parameterLevel - 3 ) << str.str() << " |" << std::endl; } -template< typename T > +template< typename ParameterType > void Logger :: writeParameter( const String& label, - const T& value, - int parameterLevel ) + const ParameterType& value, + int parameterLevel ) { stream << "| "; int i; diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index 1ccc27537..f347c4510 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -54,7 +54,7 @@ class Timer void start(); ///// - /// \brief Returs the elapsed time on given timer. + /// \brief Returns the elapsed time on given timer. /// /// It returns the elapsed time between calling the start() and stop() functions. /// Starts counting the real time after the function start() is called and -- GitLab From 1b5b560cdaad596819fac789a5ce86528a986d77 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Tue, 20 Nov 2018 15:52:03 +0100 Subject: [PATCH 031/111] Added adjustments in documentation of Timer and File. --- src/Examples/FileExample.cpp | 3 +-- src/Examples/TimerExample.cpp | 3 +++ src/TNL/File.h | 20 ++++++++++++++------ src/TNL/Timer.h | 14 +++++++------- 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/Examples/FileExample.cpp b/src/Examples/FileExample.cpp index e0e81ab91..f5f3912dd 100644 --- a/src/Examples/FileExample.cpp +++ b/src/Examples/FileExample.cpp @@ -19,7 +19,6 @@ int main() file.read( title2, 4); file.close(); - if fileExists( "new-file.tnl" ) - std::remove( "new-file.tnl" ); + cout << "title2:" << title2 < #include +#include using namespace TNL; using namespace std; int main() { + unsigned int microseconds = 0.5; Timer time; time.start(); + usleep(microseconds); time.stop(); time.getRealTime(); time.reset(); diff --git a/src/TNL/File.h b/src/TNL/File.h index bb31cdcd2..20fb1fe7b 100644 --- a/src/TNL/File.h +++ b/src/TNL/File.h @@ -37,7 +37,7 @@ enum class IOMode const size_t FileGPUvsCPUTransferBufferSize = 5 * 2<<20; -///\brief Class file is aimed mainly for the binary data. +///\brief Class file is aimed mainly for saving and loading binary data. /// /// \par Example /// \include FileExample.cpp @@ -59,10 +59,10 @@ class File public: - /// Basic constructor. + /// \brief Basic constructor. File(); - /// Destructor. + /// \brief Destructor. ~File(); ///// @@ -95,8 +95,12 @@ class File /// \brief Method that can write particular data type from given file into GPU. (Function that gets particular elements from given file.) /// - /// Returns boolean value based on the succes in reading elements from given file. - /// \param buffer Pointer in memory (where the read elements are stored?). + /// Returns \e true when the elements are successfully read from given file. Otherwise returns \e false. + /// + /// \tparam Type Type of data. + /// \tparam Device Place where data are stored after reading from file. For example Devices::Host or Devices::Cuda. + /// \tparam Index Type of index by which the elements are indexed. + /// \param buffer Pointer in memory where the elements are loaded and stored after reading. /// \param elements Number of elements the user wants to get (read) from given file. template< typename Type, typename Device = Devices::Host, typename Index = int > bool read( Type* buffer, @@ -109,7 +113,11 @@ class File /// \brief Method that can write particular data type from CPU into given file. (Function that writes particular elements into given file.) /// /// Returns boolean value based on the succes in writing elements into given file. - /// \param buffer Pointer in memory. + /// + /// \tparam Type Type of data. + /// \tparam Device Place from where data are loaded before writing into file. For example Devices::Host or Devices::Cuda. + /// \tparam Index Type of index by which the elements are indexed. + /// \param buffer Pointer in memory from where the elements are loaded before writing into file. /// \param elements Number of elements the user wants to write into the given file. template< typename Type, typename Device = Devices::Host, typename Index = int > bool write( const Type* buffer, diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index f347c4510..b90fabce7 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -49,21 +49,21 @@ class Timer /// \brief Starts timer. /// /// Starts all time and cycle measurements such as real time, CPU time and - /// CPU cycles. Function start() can be used also after using stop() function. + /// CPU cycles. Method start() can be used also after using stop() method. /// The timer then continues measuring the time without reseting. void start(); ///// /// \brief Returns the elapsed time on given timer. /// - /// It returns the elapsed time between calling the start() and stop() functions. - /// Starts counting the real time after the function start() is called and - /// pauses when the function stop() is called. + /// It returns the elapsed time between calling the start() and stop() methods. + /// Starts counting the real time after the method start() is called and + /// pauses when the method stop() is called. /// If the timer have been started more then once without resetting, /// the real time is counted by adding all intervals (between start and stop - /// functions) together. + /// methods) together. /// This function can be called while the timer is running, there is no - /// need to use stop() function first. + /// need to use stop() method first. double getRealTime() const; ///// @@ -86,7 +86,7 @@ class Timer /// \brief Function for measuring the real time. /// - /// Returns the current calendar time. + /// Returns number of seconds since Epoch, 1970-01-01 00:00:00 UTC. double readRealTime() const; /// \brief Function for measuring the CPU time. -- GitLab From bbcf705355a2986d914587a9803217009df6f6eb Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Wed, 21 Nov 2018 12:15:43 +0100 Subject: [PATCH 032/111] Made changes in TimerExample. --- src/Examples/TimerExample.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Examples/TimerExample.cpp b/src/Examples/TimerExample.cpp index 4ca3e5827..5817198c0 100644 --- a/src/Examples/TimerExample.cpp +++ b/src/Examples/TimerExample.cpp @@ -12,7 +12,8 @@ int main() time.start(); usleep(microseconds); time.stop(); - time.getRealTime(); + cout << "before reset:" << time.getRealTime() << endl; time.reset(); + cout << "after reset:" << time.getRealTime() << endl; } -- GitLab From 92eccd343657337c86ebdca0a8b65c0f68a03954 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Wed, 21 Nov 2018 12:50:32 +0100 Subject: [PATCH 033/111] Modified the Timer documentation. --- src/Examples/TimerExample.cpp | 1 + src/TNL/Timer.h | 23 +++++++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/Examples/TimerExample.cpp b/src/Examples/TimerExample.cpp index 5817198c0..49bafb25c 100644 --- a/src/Examples/TimerExample.cpp +++ b/src/Examples/TimerExample.cpp @@ -15,5 +15,6 @@ int main() cout << "before reset:" << time.getRealTime() << endl; time.reset(); cout << "after reset:" << time.getRealTime() << endl; + // writeLog example } diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index b90fabce7..05a6de3ed 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -17,6 +17,7 @@ class Logger; /// \brief Class for time measuring. /// +/// Counts the elapsed time in seconds between the start() and stop() methods. /// \par Example /// \include TimerExample.cpp // \par Output @@ -56,7 +57,7 @@ class Timer ///// /// \brief Returns the elapsed time on given timer. /// - /// It returns the elapsed time between calling the start() and stop() methods. + /// It returns the elapsed time (in seconds) between calling the start() and stop() methods. /// Starts counting the real time after the method start() is called and /// pauses when the method stop() is called. /// If the timer have been started more then once without resetting, @@ -69,17 +70,23 @@ class Timer ///// /// \brief Returns the elapsed CPU time on given timer. /// - /// CPU time is the time that measures how long it takes processor - /// to complete all computations. + /// The CPU time is measured in seconds. + /// CPU time is the amount of time for which a central processing unit (CPU) + /// was used for processing instructions of a computer program or operating system. + /// The CPU time is measured by adding the amount of CPU time between start() and stop() + /// methods together. double getCPUTime() const; - /// Returns the number of CPU cycles (machine cycles). + /// \brief Returns the number of CPU cycles (machine cycles). + /// + /// CPU cycles are counted by adding the number of CPU cycles between start() and stop() + /// methods together. unsigned long long int getCPUCycles() const; /// \brief Writes a record into the \e logger. /// /// \param logger - /// \param logLevel A whole number from zero up, which indicates the indent. + /// \param logLevel A non-negative integer recording the log record indent. bool writeLog( Logger& logger, int logLevel = 0 ) const; protected: @@ -91,8 +98,8 @@ class Timer /// \brief Function for measuring the CPU time. /// - /// CPU time is the time that measures how long it takes processor - /// to complete all computations. + /// CPU time is the amount of time for which a central processing unit (CPU) + /// was used for processing instructions of a computer program or operating system. double readCPUTime() const; /// \brief Function for counting the number of CPU cycles (machine cycles). @@ -106,7 +113,7 @@ class Timer /// \brief Saves information about the state of given timer. /// - /// Knows whether the timer is currently stopped or not. + /// Knows whether the timer is currently stopped or it is running. bool stopState; /// \brief Time Stamp Counter returning number of CPU cycles since reset. -- GitLab From a9a09230799b3c7618c52008b1dab23ec7e6be94 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Wed, 21 Nov 2018 13:33:54 +0100 Subject: [PATCH 034/111] Added Logger documentation. --- src/TNL/Containers/List.h | 1 + src/TNL/Logger.h | 20 +++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/TNL/Containers/List.h b/src/TNL/Containers/List.h index 3954b014e..96cd236f7 100644 --- a/src/TNL/Containers/List.h +++ b/src/TNL/Containers/List.h @@ -59,6 +59,7 @@ template< class T > class List /// Destroys the list. References to the values in the list become invalid. ~List(); + /// Returns the type of list. static String getType(); /// Returns \e true if the list contains no items, otherwise returns \e false. diff --git a/src/TNL/Logger.h b/src/TNL/Logger.h index bddcfeeeb..d73594d2c 100644 --- a/src/TNL/Logger.h +++ b/src/TNL/Logger.h @@ -15,7 +15,7 @@ namespace TNL { -/// Vytvari tabulku s logem vypoctu +/// Creates calculations log in the form of a table. class Logger { public: @@ -36,12 +36,12 @@ class Logger /// \param title String containing the header title. void writeHeader( const String& title ); - /// \brief Creates separator for structuring the log. + /// \brief Creates separator used as a log structure. void writeSeparator(); /// \brief Inserts information about various system parameters into the log. /// - /// \param parameters is a container with configuration parameters + /// \param parameters A container with configuration parameters. bool writeSystemInformation( const Config::ParameterContainer& parameters ); ///// @@ -50,6 +50,14 @@ class Logger /// \param label Label to be printed to the log together with the current time. void writeCurrentTime( const char* label ); + /// \brief Inserts parameter information into the log. + /// + /// \tparam ParameterType Type of the parameter. + /// \param label Description/label of the line. + /// \param parameterName Name of the parameter. + /// \param parameters A container with configuration parameters. + /// \param parameterLevel Integer defining the indent used in the log. + // TODO: add units template< typename ParameterType > void writeParameter( const String& label, @@ -57,6 +65,12 @@ class Logger const Config::ParameterContainer& parameters, int parameterLevel = 0 ); + /// \brief Inserts parameter information into the log. + /// + /// \tparam ParameterType Type of the parameter. + /// \param label Description/label of the line. + /// \param value Parameter value. + /// \param parameterLevel Integer defining the indent used in the log. template< typename ParameterType > void writeParameter( const String& label, const ParameterType& value, -- GitLab From 602e4d487b0bb4e0d63c4db4eb8aa67d5deb9b9c Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 26 Nov 2018 12:23:41 +0100 Subject: [PATCH 035/111] Fixed Logger documentation. --- src/TNL/Logger.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/TNL/Logger.h b/src/TNL/Logger.h index d73594d2c..7a6472bfa 100644 --- a/src/TNL/Logger.h +++ b/src/TNL/Logger.h @@ -33,7 +33,7 @@ class Logger /// /// The header usually contains title of the program. /// - /// \param title String containing the header title. + /// \param title A String containing the header title. void writeHeader( const String& title ); /// \brief Creates separator used as a log structure. @@ -78,8 +78,10 @@ class Logger protected: + /// \brief Integer defining the width of the log. int width; + /// \brief Output stream where the log will be printed out. std::ostream& stream; }; -- GitLab From 929b7675b8ec6e8f96b4077d32b930137265239a Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 26 Nov 2018 12:56:52 +0100 Subject: [PATCH 036/111] Fixed File documentation. --- src/TNL/File.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/TNL/File.h b/src/TNL/File.h index 20fb1fe7b..afa5631f6 100644 --- a/src/TNL/File.h +++ b/src/TNL/File.h @@ -66,12 +66,13 @@ class File ~File(); ///// - /// \brief Opens given file. + /// \brief Attempts to open given file and returns \e true after the file is + /// successfully opened. Otherwise returns \e false. /// /// Opens file with given \e fileName and returns true/false based on the success in opening the file. /// \param fileName String which indicates name of the file user wants to open. /// \param mode Indicates what user needs to do with opened file. - /// Modes to choose: IOMode::read or IOMode::write or IOMode::undefined. + /// Modes to choose: IOMode::read, IOMode::write or IOMode::undefined. bool open( const String& fileName, const IOMode mode ); @@ -81,13 +82,13 @@ class File return this->fileName; } - /// Returns number of read elements. + /// \brief Returns number of read elements. long int getReadElements() const { return this->readElements; } - /// Returns number of written elements. + /// \brief Returns number of written elements. long int getWrittenElements() const { return this->writtenElements; @@ -112,12 +113,12 @@ class File /// \brief Method that can write particular data type from CPU into given file. (Function that writes particular elements into given file.) /// - /// Returns boolean value based on the succes in writing elements into given file. + /// Returns \e true when the elements are successfully written into given file. Otherwise returns \e false. /// /// \tparam Type Type of data. - /// \tparam Device Place from where data are loaded before writing into file. For example Devices::Host or Devices::Cuda. + /// \tparam Device Place from where the data are loaded before writing into file. For example Devices::Host or Devices::Cuda. /// \tparam Index Type of index by which the elements are indexed. - /// \param buffer Pointer in memory from where the elements are loaded before writing into file. + /// \param buffer Pointer in memory where the elements are loaded from before writing into file. /// \param elements Number of elements the user wants to write into the given file. template< typename Type, typename Device = Devices::Host, typename Index = int > bool write( const Type* buffer, @@ -127,7 +128,8 @@ class File template< typename Type, typename Device = Devices::Host > bool write( const Type* buffer ); - /// \brief Closes given file and returns true/false based on the success in closing the file. + /// \brief Attempts to close given file and returns \e true when the file is + /// successfully closed. Otherwise returns \e false. bool close(); protected: -- GitLab From 0a7815cd1694ea97f86ae444a7b6d2dd3e7921e1 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 26 Nov 2018 13:41:39 +0100 Subject: [PATCH 037/111] Fixed String documentation. --- src/TNL/String.h | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/TNL/String.h b/src/TNL/String.h index 37d3878f2..0730af6f6 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -48,6 +48,7 @@ class String /// Constructs a string initialized with the 8-bit string \e c, excluding /// the given number of \e prefix_cut_off and \e sufix_cut_off characters. /// + /// @param c Pointer to an array of characters. /// @param prefix_cut_off Determines the length of the prefix that is going /// to be omitted from the string \e c. /// @param sufix_cut_off Determines the length of the sufix that is going @@ -61,13 +62,14 @@ class String int prefix_cut_off = 0, int sufix_cut_off = 0 ); - /// Returns type of string - String. + /// \brief Returns type of string - String. static String getType(); ///// /// \brief Copy constructor. /// /// Constructs a copy of the string \e str. + /// @param str Another string object, whose value is copied. String( const String& str ); /// \brief Converts anything to a string. @@ -96,7 +98,7 @@ class String /// \include StringExampleGetSize.out int getSize() const; - /// Returns size of allocated storage for given string. + /// \brief Returns size of allocated storage for given string. /// /// \par Example /// \include StringExampleGetAllocatedSize.cpp @@ -175,23 +177,23 @@ class String ///// // Operators for Strings. - /// This function assigns \e str to this string and returns a reference to + /// \brief This function assigns \e str to this string and returns a reference to /// this string. String& operator=( const String& str ); - /// This function appends the string \e str onto the end of this string + /// \brief This function appends the string \e str onto the end of this string /// and returns a reference to this string. String& operator+=( const String& str ); - /// This function concatenates strings \e str and returns a newly + /// \brief This function concatenates strings \e str and returns a newly /// constructed string object. String operator+( const String& str ) const; /// \brief This function overloads operator==(). /// - /// It returns \c true if this string is equal to \e str, otherwise returns + /// Returns \c true if this string is equal to \e str, otherwise returns /// \c false. bool operator==( const String& str ) const; /// \brief This function overloads operator!=(). /// - /// It returns \c true if this string is not equal to \e str, otherwise + /// Returns \c true if this string is not equal to \e str, otherwise /// returns \c false. bool operator!=( const String& str ) const; @@ -200,15 +202,15 @@ class String /// \brief This function overloads operator=(). /// - /// It assigns character \e str to this string. + /// Assigns character \e str to this string. String& operator=( char str ); /// \brief This function overloads operator+=(). /// - /// It appends character \e str to this string. + /// Appends character \e str to this string. String& operator+=( char str ); - // This function concatenates strings and returns a newly constructed string object. + // \brief This function concatenates strings and returns a newly constructed string object. String operator+( char str ) const; - // This function concatenates strings and returns a newly constructed string object. + // \brief This function concatenates strings and returns a newly constructed string object. bool operator==( char str ) const; /// \brief This function overloads operator!=(). bool operator!=( char str ) const; @@ -280,21 +282,21 @@ class String protected: - /// Pointer to char ended with zero byte + /// \brief Pointer to char ended with zero byte. char* string; - /// Length of allocated piece of memory. + /// \brief Length of allocated piece of memory. int length; }; // class String -/// Returns concatenation of \e string1 and \e string2. +/// \brief Returns concatenation of \e string1 and \e string2. String operator+( char string1, const String& string2 ); -/// Returns concatenation of \e string1 and \e string2. +/// \brief Returns concatenation of \e string1 and \e string2. String operator+( const char* string1, const String& string2 ); -/// Performs the string output to a stream +/// \brief Performs the string output to a stream std::ostream& operator<<( std::ostream& stream, const String& str ); template< typename T > -- GitLab From 66102ab6b5e76de6da9cbcb2eb803144bce37782 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 26 Nov 2018 13:47:06 +0100 Subject: [PATCH 038/111] Fixed Timer documentation. --- src/TNL/Timer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index 05a6de3ed..bcbeaca28 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -60,7 +60,7 @@ class Timer /// It returns the elapsed time (in seconds) between calling the start() and stop() methods. /// Starts counting the real time after the method start() is called and /// pauses when the method stop() is called. - /// If the timer have been started more then once without resetting, + /// If the timer has been started more then once without resetting, /// the real time is counted by adding all intervals (between start and stop /// methods) together. /// This function can be called while the timer is running, there is no -- GitLab From 7abd0b1ae547948cadbdf20abbabc13350406bd9 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 26 Nov 2018 13:55:24 +0100 Subject: [PATCH 039/111] Fixed FileName documentation. --- src/TNL/FileName.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/TNL/FileName.h b/src/TNL/FileName.h index d12e82835..312f2f34e 100644 --- a/src/TNL/FileName.h +++ b/src/TNL/FileName.h @@ -24,6 +24,9 @@ String getFileExtension( const String fileName ); void removeFileExtension( String& file_name ); +/// \brief Class for creating the full name of a file. +/// +/// Merges base name, index number and extention to create the full name of a file. class FileName { public: @@ -42,7 +45,7 @@ class FileName /// \brief Sets the extension of given file. /// /// Sets \e extension as suffix of a file name. - /// @param extension String that specifies extension of file (without dot). + /// @param extension A String that specifies extension of file (without dot). /// Suffix of a file name. E.g. doc, xls, tnl. void setExtension( const String& extension ); @@ -58,7 +61,7 @@ class FileName /// @param digitsCount Integer - number of digits. void setDigitsCount( const int digitsCount ); - /// Creates appropriate name for given file. + /// \brief Creates appropriate name for given file. /// /// Creates particular file name using \e fileNameBase, \e digitsCount, /// \e index and \e extension. -- GitLab From e8c5dc89f7dfe647a45475a3d59c4fc0b4dc8cc1 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 26 Nov 2018 16:00:35 +0100 Subject: [PATCH 040/111] Started with Math and ParameterContainer documentation. --- src/TNL/Config/ParameterContainer.h | 9 +++++++++ src/TNL/Math.h | 27 ++++++++++++++++++--------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/TNL/Config/ParameterContainer.h b/src/TNL/Config/ParameterContainer.h index 2450c3809..55ef460d1 100644 --- a/src/TNL/Config/ParameterContainer.h +++ b/src/TNL/Config/ParameterContainer.h @@ -44,8 +44,17 @@ class ParameterContainer { public: + /** + * \brief Basic constructor. + */ ParameterContainer(); + /** + * \brief Adds parameter + * @tparam T Type of parameter value. + * @param name Name of the parameter. + * @param value Value assigned to the parameter. + */ template< class T > bool addParameter( const String& name, const T& value ); diff --git a/src/TNL/Math.h b/src/TNL/Math.h index 67e9f5e08..b32244c9c 100644 --- a/src/TNL/Math.h +++ b/src/TNL/Math.h @@ -19,7 +19,7 @@ namespace TNL { /*** - * This function returns minimum of two numbers. + * \brief This function returns minimum of two numbers. * GPU device code uses the functions defined in the CUDA's math_functions.h, * MIC uses trivial override and host uses the STL functions. */ @@ -43,7 +43,7 @@ ResultType min( const T1& a, const T2& b ) /*** - * This function returns maximum of two numbers. + * \brief This function returns maximum of two numbers. * GPU device code uses the functions defined in the CUDA's math_functions.h, * MIC uses trivial override and host uses the STL functions. */ @@ -66,7 +66,7 @@ ResultType max( const T1& a, const T2& b ) } /*** - * This function returns absolute value of given number. + * \brief This function returns absolute value of given number. */ template< class T > __cuda_callable__ inline @@ -87,7 +87,7 @@ T abs( const T& n ) } /*** - * This function returns argument of minimum of two numbers. + * \brief This function returns argument of minimum of two numbers. */ template< typename T1, typename T2, typename ResultType = typename std::common_type< T1, T2 >::type > __cuda_callable__ inline @@ -97,7 +97,7 @@ ResultType argMin( const T1& a, const T2& b ) } /*** - * This function returns argument of maximum of two numbers. + * \brief This function returns argument of maximum of two numbers. */ template< typename T1, typename T2, typename ResultType = typename std::common_type< T1, T2 >::type > __cuda_callable__ @@ -107,7 +107,7 @@ ResultType argMax( const T1& a, const T2& b ) } /*** - * This function returns argument of minimum of absolute values of two numbers. + * \brief This function returns argument of minimum of absolute values of two numbers. */ template< typename T1, typename T2, typename ResultType = typename std::common_type< T1, T2 >::type > __cuda_callable__ inline @@ -117,7 +117,7 @@ ResultType argAbsMin( const T1& a, const T2& b ) } /*** - * This function returns argument of maximum of absolute values of two numbers. + * \brief This function returns argument of maximum of absolute values of two numbers. */ template< typename T1, typename T2, typename ResultType = typename std::common_type< T1, T2 >::type > __cuda_callable__ @@ -137,7 +137,9 @@ ResultType pow( const T1& base, const T2& exp ) #endif } - +/** + * \brief This function returns square root of a value. + */ template< typename T > __cuda_callable__ inline T sqrt( const T& value ) @@ -149,7 +151,9 @@ T sqrt( const T& value ) #endif } - +/** + * \brief This function swaps values of two parameters. + */ template< typename Type > __cuda_callable__ void swap( Type& a, Type& b ) @@ -159,6 +163,11 @@ void swap( Type& a, Type& b ) b = tmp; } +/** + * \brief This function represents the signum function. + * + * It extracts the sign of a real number. + */ template< class T > __cuda_callable__ T sign( const T& a ) -- GitLab From 7e018945e53f8d5c139c5e2cbc5d41fe7f831f39 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Wed, 28 Nov 2018 13:37:49 +0100 Subject: [PATCH 041/111] Added documentation of Math, Assert and ParameterContainer. --- src/TNL/Assert.h | 7 ++++++ src/TNL/Config/ParameterContainer.h | 29 ++++++++++++++++++---- src/TNL/Math.h | 37 +++++++++++++++++++++++++---- src/TNL/Object.h | 5 ++-- 4 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/TNL/Assert.h b/src/TNL/Assert.h index 6d13e35b1..34b721fe6 100644 --- a/src/TNL/Assert.h +++ b/src/TNL/Assert.h @@ -33,6 +33,13 @@ #if defined(NDEBUG) || defined(HAVE_MIC) // empty macros for optimized build +/** + * \brief Assert that the expression \e val evaluates to \e true. + * + * The assertion succeeds if, and only if, \e val evaluates to equal to \e true. + * On success the test continues without any side effects. + * On failure the test is terminated with the error message \e msg. + */ #define TNL_ASSERT_TRUE( val, msg ) #define TNL_ASSERT_FALSE( val, msg ) #define TNL_ASSERT_EQ( val1, val2, msg ) diff --git a/src/TNL/Config/ParameterContainer.h b/src/TNL/Config/ParameterContainer.h index 55ef460d1..f524d2917 100644 --- a/src/TNL/Config/ParameterContainer.h +++ b/src/TNL/Config/ParameterContainer.h @@ -50,10 +50,11 @@ class ParameterContainer ParameterContainer(); /** - * \brief Adds parameter - * @tparam T Type of parameter value. - * @param name Name of the parameter. - * @param value Value assigned to the parameter. + * \brief Adds new parameter to the ParameterContainer. + * + * \tparam T Type of parameter value. + * \param name Name of the new parameter. + * \param value Value assigned to the parameter. */ template< class T > bool addParameter( const String& name, const T& value ); @@ -61,8 +62,20 @@ class ParameterContainer bool addParameter( const String& name, const String& value ); + /** + * \brief Checks whether the parameter \e name already exists in ParameterContainer. + * + * \param name Name of the parameter. + */ bool checkParameter( const String& name ) const; + /** + * \brief Assigns new \e value to the parameter \e name. + * + * \tparam T Type of the parameter value. + * \param name Name of parameter. + * \param value Value of type T assigned to the parameter. + */ template< class T > bool setParameter( const String& name, const T& value ); @@ -89,6 +102,11 @@ class ParameterContainer return false; } + /** + * \brief Returns parameter value. + * + * \param name Name of parameter. + */ template< class T > const T& getParameter( const String& name ) const { int i; @@ -104,6 +122,9 @@ class ParameterContainer //! Broadcast to other nodes in MPI cluster // void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); + /** + * \brief Basic destructor. + */ ~ParameterContainer(); protected: diff --git a/src/TNL/Math.h b/src/TNL/Math.h index b32244c9c..34cd91eeb 100644 --- a/src/TNL/Math.h +++ b/src/TNL/Math.h @@ -20,6 +20,7 @@ namespace TNL { /*** * \brief This function returns minimum of two numbers. + * * GPU device code uses the functions defined in the CUDA's math_functions.h, * MIC uses trivial override and host uses the STL functions. */ @@ -44,6 +45,7 @@ ResultType min( const T1& a, const T2& b ) /*** * \brief This function returns maximum of two numbers. + * * GPU device code uses the functions defined in the CUDA's math_functions.h, * MIC uses trivial override and host uses the STL functions. */ @@ -65,8 +67,8 @@ ResultType max( const T1& a, const T2& b ) #endif } -/*** - * \brief This function returns absolute value of given number. +/** + * \brief This function returns absolute value of given number \e n. */ template< class T > __cuda_callable__ inline @@ -126,6 +128,9 @@ ResultType argAbsMax( const T1& a, const T2& b ) return ( TNL::abs( a ) > TNL::abs( b ) ) ? a : b; } +/** + * \brief This function returns the result of \e base to the power of \e exp. + */ template< typename T1, typename T2, typename ResultType = typename std::common_type< T1, T2 >::type > __cuda_callable__ inline ResultType pow( const T1& base, const T2& exp ) @@ -138,7 +143,7 @@ ResultType pow( const T1& base, const T2& exp ) } /** - * \brief This function returns square root of a value. + * \brief This function returns square root of the given \e value. */ template< typename T > __cuda_callable__ inline @@ -153,6 +158,8 @@ T sqrt( const T& value ) /** * \brief This function swaps values of two parameters. + * + * It assigns the value of \e a to the parameter \e b and vice versa. */ template< typename Type > __cuda_callable__ @@ -166,7 +173,9 @@ void swap( Type& a, Type& b ) /** * \brief This function represents the signum function. * - * It extracts the sign of a real number. + * It extracts the sign of the number \e a. In other words, the signum function projects + * negative numbers to value -1, positive numbers to value 1 and zero to value 0. + * Non-zero complex numbers are projected to the unit circle. */ template< class T > __cuda_callable__ @@ -177,6 +186,14 @@ T sign( const T& a ) return ( T ) 1; } +/** + * \brief This function tests whether the given real number is small. + * + * It tests whether the number \e v is in \e tolerance, in other words, whether + * \e v in absolute value is less then or equal to \e tolerance. + * @param v Real number. + * @param tolerance Critical value which is set to 0.00001 by defalt. + */ template< typename Real > __cuda_callable__ bool isSmall( const Real& v, @@ -185,12 +202,24 @@ bool isSmall( const Real& v, return ( -tolerance <= v && v <= tolerance ); } +/** + * \brief This function divides \e num by \e div and rounds up the result. + * + * @param num An integer considered as dividend. + * @param div An integer considered as divisor. + */ __cuda_callable__ inline int roundUpDivision( const int num, const int div ) { return num / div + ( num % div != 0 ); } +/** + * \brief This function rounds \e number to the nearest multiple of number \e multiple. + * + * @param number Integer we want to round. + * @param multiple Integer. + */ __cuda_callable__ inline int roundToMultiple( int number, int multiple ) { diff --git a/src/TNL/Object.h b/src/TNL/Object.h index 4b37d8a77..b4f225075 100644 --- a/src/TNL/Object.h +++ b/src/TNL/Object.h @@ -17,8 +17,9 @@ namespace TNL { -//! This is basic class for all 'large' objects like matrices, meshes, grids, solvers etc. -/*! +/** + * \brief This is the basic class for all 'large' objects like matrices, meshes, grids, solvers, etc.. + * * Objects like numerical grids, meshes, matrices large vectors etc. * are inherited by this class. This class provides name for such objects. Giving * a name to each bigger object is compulsory. The name can help to locate -- GitLab From 34c6fc36860e7789b9ce3bf396ef91a4ce9c83e4 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Fri, 30 Nov 2018 15:35:38 +0100 Subject: [PATCH 042/111] Added Assert documentation. --- src/TNL/Assert.h | 57 +++++++++++++++++++++++++++++++++++++++++++++++- src/TNL/Math.h | 2 +- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/TNL/Assert.h b/src/TNL/Assert.h index 34b721fe6..dabd69a97 100644 --- a/src/TNL/Assert.h +++ b/src/TNL/Assert.h @@ -34,20 +34,75 @@ // empty macros for optimized build /** - * \brief Assert that the expression \e val evaluates to \e true. + * \brief Asserts that the expression \e val evaluates to \e true. * * The assertion succeeds if, and only if, \e val evaluates to equal to \e true. * On success the test continues without any side effects. * On failure the test is terminated with the error message \e msg. */ #define TNL_ASSERT_TRUE( val, msg ) +/** + * \brief Asserts that the expression \e val evaluates to \e false. + * + * The assertion succeeds if, and only if, \e val evaluates to equal to \e false. + * On success the test continues without any side effects. + * On failure the test is terminated with the error message \e msg. + */ #define TNL_ASSERT_FALSE( val, msg ) +/** + * \brief Asserts that the expression \e val1 is equal to \e val2. + * + * The assertion succeeds if, and only if, \e val1 and \e val2 are equal. + * On success the test continues without any side effects. + * On failure the test is terminated with the error message \e msg. + */ #define TNL_ASSERT_EQ( val1, val2, msg ) +/** + * \brief Asserts that the expression \e val1 is not equal to \e val2. + * + * The assertion succeeds if, and only if, \e val1 and \e val2 are not equal. + * On success the test continues without any side effects. + * On failure the test is terminated with the error message \e msg. + */ #define TNL_ASSERT_NE( val1, val2, msg ) +/** + * \brief Asserts that the expression \e val1 is less than or equal to \e val2. + * + * The assertion succeeds if, and only if, \e val1 is less than or equal to \e val2. + * On success the test continues without any side effects. + * On failure the test is terminated with the error message \e msg. + */ #define TNL_ASSERT_LE( val1, val2, msg ) +/** + * \brief Asserts that the expression \e val1 is less than \e val2. + * + * The assertion succeeds if, and only if, \e val1 is less than \e val2. + * On success the test continues without any side effects. + * On failure the test is terminated with the error message \e msg. + */ #define TNL_ASSERT_LT( val1, val2, msg ) +/** + * \brief Asserts that the expression \e val1 is greater than or equal to \e val2. + * + * The assertion succeeds if, and only if, \e val1 is greater than or equal to \e val2. + * On success the test continues without any side effects. + * On failure the test is terminated with the error message \e msg. + */ #define TNL_ASSERT_GE( val1, val2, msg ) +/** + * \brief Asserts that the expression \e val1 is greater than \e val2. + * + * The assertion succeeds if, and only if, \e val1 is greater than \e val2. + * On success the test continues without any side effects. + * On failure the test is terminated with the error message \e msg. + */ #define TNL_ASSERT_GT( val1, val2, msg ) +/** + * \brief Asserts that the specified \e ___tnl__assert_condition is valid. + * + * The assertion succeeds if, and only if, ___tnl__assert_condition is valid. + * On success the test continues without any side effects. + * On failure the test is terminated with the error message \e ___tnl__assert_command. #define TNL_ASSERT( ___tnl__assert_condition, ___tnl__assert_command ) #else /* #ifdef NDEBUG */ diff --git a/src/TNL/Math.h b/src/TNL/Math.h index 34cd91eeb..12cab18d8 100644 --- a/src/TNL/Math.h +++ b/src/TNL/Math.h @@ -215,7 +215,7 @@ inline int roundUpDivision( const int num, const int div ) } /** - * \brief This function rounds \e number to the nearest multiple of number \e multiple. + * \brief This function rounds up \e number to the nearest multiple of number \e multiple. * * @param number Integer we want to round. * @param multiple Integer. -- GitLab From 6e2c3cc139d9bc85d9d59490cb8622fbf7f4d8bc Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Fri, 30 Nov 2018 16:01:42 +0100 Subject: [PATCH 043/111] Modified the ParameterContainer documentation. --- src/TNL/Config/ParameterContainer.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/TNL/Config/ParameterContainer.h b/src/TNL/Config/ParameterContainer.h index f524d2917..b475c53ec 100644 --- a/src/TNL/Config/ParameterContainer.h +++ b/src/TNL/Config/ParameterContainer.h @@ -82,6 +82,17 @@ class ParameterContainer bool setParameter( const String& name, const String& value ); + /** + * \brief Checks whether the parameter \e name is given the \e value. + * + * Returns \e true if the parameter \e name is given the \e value. + * If the parameter does not have any value or has different value then the given + * \e value the method returns \e false and shows message when \e verbose is \e true. + * + * @param name Name of parameter. + * @param value Value of type T we want to check whether is assigned to the parameter. + * @param verbose Boolean value defining whether to show error message (when true) or not (when false). + */ template< class T > bool getParameter( const String& name, T& value, bool verbose = true ) const -- GitLab From 35f44e5c1d66766bfbb003a74306cd8230bcd77d Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 3 Dec 2018 10:26:47 +0100 Subject: [PATCH 044/111] Improved documentation of Containers/List. --- src/TNL/Containers/List.h | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/TNL/Containers/List.h b/src/TNL/Containers/List.h index 96cd236f7..68e521a62 100644 --- a/src/TNL/Containers/List.h +++ b/src/TNL/Containers/List.h @@ -26,9 +26,9 @@ template< class T > class ListDataElement; /*! To acces elements in the list one can use method getSize() and operator[](). To add elements there are methods Append(), Prepend() and Insert() to insert an element at given - position. To erase particular element there is merthod + position. To erase particular element there is method Erase() taking the element position. To erase all elements - there is method EraseAll. There are also alternatives DeepErase() + there is method reset(). There are also alternatives DeepErase() and DeepEraseAll() to free dynamicaly allocated data inside the data elements. The list stores pointer to last accesed element so if one goes @@ -51,7 +51,7 @@ template< class T > class List /// \brief Copy constructor. /// /// Construct a copy of \e list. - /// @param list Name of another list. + /// \param list Name of another list. List( const List& list ); /// \brief Destructor. @@ -96,18 +96,27 @@ template< class T > class List bool Insert( const T& data, const int& ind ); /// Appends copy of another list. + /// + /// \param lst Name of another list. bool AppendList( const List< T >& lst ); /// Prepends copy of another list. + /// + /// \param lst Name of another list. bool PrependList( const List< T >& lst ); + /// Transforms list to an \e array. template< typename Array > void toArray( Array& array ); /// Erases data element at given position. + /// + /// \param ind Index of the data element one chooses to remove. void Erase( const int& ind ); /// Erases data element with contained data at given position. + /// + /// \param ind Index of the data element one chooses to remove. void DeepErase( const int& ind ); /// Erases all data elements. @@ -119,15 +128,23 @@ template< class T > class List void DeepEraseAll(); /// Saves the list in binary format. + /// + /// \param file Name of file. bool Save( File& file ) const; /// Saves the list in binary format using method save of type T. + /// + /// \param file Name of file. bool DeepSave( File& file ) const; - /// Loads the list. + /// Loads the list from file. + /// + /// \param file Name of file. bool Load( File& file ); - /// Loads the list using method Load of the type T. + /// Loads the list from file using method Load of the type T. + /// + /// \param file Name of file. bool DeepLoad( File& file ); protected: -- GitLab From 8e45402f49dc55bac693432f47d20f2f891201ec Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 3 Dec 2018 11:17:39 +0100 Subject: [PATCH 045/111] Added Object documentation. --- src/TNL/Object.h | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/TNL/Object.h b/src/TNL/Object.h index b4f225075..f0b2b435f 100644 --- a/src/TNL/Object.h +++ b/src/TNL/Object.h @@ -34,16 +34,18 @@ class Object public: /**** - * Type getter. This returns the type in C++ style - for example the returned value + * \brief Type getter. + * + * Returns the type in C++ style - for example the returned value * may look as follows: "Vector< double, Devices::Cuda >". */ - static String getType(); virtual String getTypeVirtual() const; /**** - * This is used for load and save methods. + * \brief This is used for load and save methods. + * * Each object is saved as if it was stored on Devices::Host. So even Vector< double, Devices::Cuda > * is saved as Vector< double, Devices::Host >. */ @@ -51,13 +53,25 @@ class Object virtual String getSerializationTypeVirtual() const; - //! Method for saving the object to a file as a binary data + /*** + * \brief Method for saving the object to a file as a binary data. + * + * \param file Name of file object. + */ virtual bool save( File& file ) const; - //! Method for restoring the object from a file + /*** + * \brief Method for restoring the object from a file. + * + * \param file Name of file object. + */ virtual bool load( File& file ); - //! Method for restoring the object from a file + /*** + * \brief Method for restoring the object from a file. + * + * \param file Name of file object. + */ virtual bool boundLoad( File& file ); bool save( const String& fileName ) const; @@ -66,7 +80,7 @@ class Object bool boundLoad( const String& fileName ); - //! Destructor + /// Destructor. // FIXME: __cuda_callable__ would have to be added to every overriding destructor, // even if the object's constructor is not __cuda_callable__ // __cuda_callable__ -- GitLab From 1b1417ddd1559d143fcab602ca81d9a44bb198ec Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 3 Dec 2018 13:59:27 +0100 Subject: [PATCH 046/111] Added ConfigDescription documentation and added small changes in Object, Math and ParameterContainer. --- src/TNL/Config/ConfigDescription.h | 52 ++++++++++++++++++++++++++++- src/TNL/Config/ParameterContainer.h | 6 ++-- src/TNL/Math.h | 28 +++++++++++----- src/TNL/Object.h | 10 +++--- 4 files changed, 79 insertions(+), 17 deletions(-) diff --git a/src/TNL/Config/ConfigDescription.h b/src/TNL/Config/ConfigDescription.h index 37325183b..d19386958 100644 --- a/src/TNL/Config/ConfigDescription.h +++ b/src/TNL/Config/ConfigDescription.h @@ -27,8 +27,18 @@ class ConfigDescription { public: + /** + * \brief Basic constructor. + */ ConfigDescription(); + /** + * \brief Adds new entry to the configuration description. + * + * \tparam EntryType Type of the entry. + * \param name Name of the entry. + * \param description More specific information about the entry. + */ template< typename EntryType > void addEntry( const String& name, const String& description ) @@ -37,6 +47,13 @@ class ConfigDescription entries.Append( currentEntry ); } + /** + * \brief Adds new entry to the configuration description. + * + * \tparam EntryType Type of the entry. + * \param name Name of the entry. + * \param description More specific information about the entry. + */ template< typename EntryType > void addRequiredEntry( const String& name, const String& description ) @@ -44,7 +61,15 @@ class ConfigDescription currentEntry = new ConfigEntry< EntryType >( name, description, true ); entries.Append( currentEntry ); } - + + /** + * \brief Adds new entry to the configuration description. + * + * \tparam EntryType Type of the entry. + * \param name Name of the entry. + * \param description More specific information about the entry. + * \param defaultValue Default value of the entry. + */ template< typename EntryType > void addEntry( const String& name, const String& description, @@ -57,6 +82,13 @@ class ConfigDescription entries. Append( currentEntry ); } + /** + * \brief Adds new list to the configuration description. + * + * \tparam EntryType Type of the list. + * \param name Name of the list. + * \param description More specific information about the list. + */ template< typename EntryType > void addList( const String& name, const String& description ) @@ -65,6 +97,13 @@ class ConfigDescription entries.Append( currentEntry ); } + /** + * \brief Adds new list to the configuration description. + * + * \tparam EntryType Type of the list. + * \param name Name of the list. + * \param description More specific information about the list. + */ template< typename EntryType > void addRequiredList( const String& name, const String& description ) @@ -73,6 +112,14 @@ class ConfigDescription entries.Append( currentEntry ); } + /** + * \brief Adds new list to the configuration description. + * + * \tparam EntryType Type of the list. + * \param name Name of the list. + * \param description More specific information about the list. + * \param defaultValue Default value of the list. + */ template< typename EntryType > void addList( const String& name, const String& description, @@ -162,6 +209,9 @@ class ConfigDescription //bool parseConfigDescription( const char* file_name ); + /** + * \brief Basic destructor. + */ ~ConfigDescription(); protected: diff --git a/src/TNL/Config/ParameterContainer.h b/src/TNL/Config/ParameterContainer.h index b475c53ec..aac0cb6ab 100644 --- a/src/TNL/Config/ParameterContainer.h +++ b/src/TNL/Config/ParameterContainer.h @@ -89,9 +89,9 @@ class ParameterContainer * If the parameter does not have any value or has different value then the given * \e value the method returns \e false and shows message when \e verbose is \e true. * - * @param name Name of parameter. - * @param value Value of type T we want to check whether is assigned to the parameter. - * @param verbose Boolean value defining whether to show error message (when true) or not (when false). + * \param name Name of parameter. + * \param value Value of type T we want to check whether is assigned to the parameter. + * \param verbose Boolean value defining whether to show error message (when true) or not (when false). */ template< class T > bool getParameter( const String& name, T& value, diff --git a/src/TNL/Math.h b/src/TNL/Math.h index 12cab18d8..68eb1f556 100644 --- a/src/TNL/Math.h +++ b/src/TNL/Math.h @@ -18,7 +18,7 @@ namespace TNL { -/*** +/** * \brief This function returns minimum of two numbers. * * GPU device code uses the functions defined in the CUDA's math_functions.h, @@ -43,7 +43,7 @@ ResultType min( const T1& a, const T2& b ) } -/*** +/** * \brief This function returns maximum of two numbers. * * GPU device code uses the functions defined in the CUDA's math_functions.h, @@ -191,8 +191,8 @@ T sign( const T& a ) * * It tests whether the number \e v is in \e tolerance, in other words, whether * \e v in absolute value is less then or equal to \e tolerance. - * @param v Real number. - * @param tolerance Critical value which is set to 0.00001 by defalt. + * \param v Real number. + * \param tolerance Critical value which is set to 0.00001 by defalt. */ template< typename Real > __cuda_callable__ @@ -205,8 +205,8 @@ bool isSmall( const Real& v, /** * \brief This function divides \e num by \e div and rounds up the result. * - * @param num An integer considered as dividend. - * @param div An integer considered as divisor. + * \param num An integer considered as dividend. + * \param div An integer considered as divisor. */ __cuda_callable__ inline int roundUpDivision( const int num, const int div ) @@ -217,8 +217,8 @@ inline int roundUpDivision( const int num, const int div ) /** * \brief This function rounds up \e number to the nearest multiple of number \e multiple. * - * @param number Integer we want to round. - * @param multiple Integer. + * \param number Integer we want to round. + * \param multiple Integer. */ __cuda_callable__ inline int roundToMultiple( int number, int multiple ) @@ -226,12 +226,24 @@ inline int roundToMultiple( int number, int multiple ) return multiple*( number/ multiple + ( number % multiple != 0 ) ); } +/** + * \brief This function checks if \e x is an integral power of two. + * + * Returns \e true if \e x is a power of two. Otherwise returns \e false. + * \param x Integer. + */ __cuda_callable__ inline bool isPow2( int x ) { return ( ( x & ( x - 1 ) ) == 0 ); } +/** + * \brief This function checks if \e x is an integral power of two. + * + * Returns \e true if \e x is a power of two. Otherwise returns \e false. + * \param x Long integer. + */ __cuda_callable__ inline bool isPow2( long int x ) { diff --git a/src/TNL/Object.h b/src/TNL/Object.h index f0b2b435f..9725d1db5 100644 --- a/src/TNL/Object.h +++ b/src/TNL/Object.h @@ -33,7 +33,7 @@ class Object { public: - /**** + /** * \brief Type getter. * * Returns the type in C++ style - for example the returned value @@ -43,7 +43,7 @@ class Object virtual String getTypeVirtual() const; - /**** + /** * \brief This is used for load and save methods. * * Each object is saved as if it was stored on Devices::Host. So even Vector< double, Devices::Cuda > @@ -53,21 +53,21 @@ class Object virtual String getSerializationTypeVirtual() const; - /*** + /** * \brief Method for saving the object to a file as a binary data. * * \param file Name of file object. */ virtual bool save( File& file ) const; - /*** + /** * \brief Method for restoring the object from a file. * * \param file Name of file object. */ virtual bool load( File& file ); - /*** + /** * \brief Method for restoring the object from a file. * * \param file Name of file object. -- GitLab From f041b082469654c9e3b18dba1cdcf38298c30b23 Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber Date: Tue, 4 Dec 2018 10:37:06 +0100 Subject: [PATCH 047/111] Fixed unclosed comment in Assert.h Added examples to CMakeList.txt. --- src/Examples/CMakeLists.txt | 6 ++++++ src/TNL/Assert.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/Examples/CMakeLists.txt b/src/Examples/CMakeLists.txt index b8e7c574a..f15836344 100644 --- a/src/Examples/CMakeLists.txt +++ b/src/Examples/CMakeLists.txt @@ -24,5 +24,11 @@ target_link_libraries( FileExample tnl ) ADD_EXECUTABLE( StringExample StringExample.cpp ) target_link_libraries( StringExample tnl ) +ADD_EXECUTABLE( StringExampleGetSize StringExampleGetSize.cpp ) +target_link_libraries( StringExampleGetSize tnl ) + +ADD_EXECUTABLE( StringExampleGetAllocatedSize StringExampleGetAllocatedSize.cpp ) +target_link_libraries( StringExampleGetAllocatedSize tnl ) + ADD_EXECUTABLE( TimerExample TimerExample.cpp ) target_link_libraries( TimerExample tnl ) \ No newline at end of file diff --git a/src/TNL/Assert.h b/src/TNL/Assert.h index dabd69a97..d601f9c1b 100644 --- a/src/TNL/Assert.h +++ b/src/TNL/Assert.h @@ -103,6 +103,7 @@ * The assertion succeeds if, and only if, ___tnl__assert_condition is valid. * On success the test continues without any side effects. * On failure the test is terminated with the error message \e ___tnl__assert_command. + */ #define TNL_ASSERT( ___tnl__assert_condition, ___tnl__assert_command ) #else /* #ifdef NDEBUG */ -- GitLab From 18011d79d783f13e5fbd5925c8c5a80fee3f8877 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Tue, 4 Dec 2018 13:01:17 +0100 Subject: [PATCH 048/111] Added ConfigDescription documenattion. --- src/Examples/TimerExample.cpp | 2 ++ src/TNL/Assert.h | 1 + src/TNL/Config/ConfigDescription.h | 40 +++++++++++++++++++++++++++--- src/TNL/Timer.h | 2 +- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/Examples/TimerExample.cpp b/src/Examples/TimerExample.cpp index 49bafb25c..aa4036734 100644 --- a/src/Examples/TimerExample.cpp +++ b/src/Examples/TimerExample.cpp @@ -16,5 +16,7 @@ int main() time.reset(); cout << "after reset:" << time.getRealTime() << endl; // writeLog example + Logger log1(50,stream); + writeLog( log1, 0 ); } diff --git a/src/TNL/Assert.h b/src/TNL/Assert.h index dabd69a97..d601f9c1b 100644 --- a/src/TNL/Assert.h +++ b/src/TNL/Assert.h @@ -103,6 +103,7 @@ * The assertion succeeds if, and only if, ___tnl__assert_condition is valid. * On success the test continues without any side effects. * On failure the test is terminated with the error message \e ___tnl__assert_command. + */ #define TNL_ASSERT( ___tnl__assert_condition, ___tnl__assert_command ) #else /* #ifdef NDEBUG */ diff --git a/src/TNL/Config/ConfigDescription.h b/src/TNL/Config/ConfigDescription.h index d19386958..833e99a47 100644 --- a/src/TNL/Config/ConfigDescription.h +++ b/src/TNL/Config/ConfigDescription.h @@ -48,7 +48,7 @@ class ConfigDescription } /** - * \brief Adds new entry to the configuration description. + * \brief Adds new entry to the configuration description, that requires set value. * * \tparam EntryType Type of the entry. * \param name Name of the entry. @@ -98,7 +98,7 @@ class ConfigDescription } /** - * \brief Adds new list to the configuration description. + * \brief Adds new list to the configuration description, that requires specific value. * * \tparam EntryType Type of the list. * \param name Name of the list. @@ -132,6 +132,13 @@ class ConfigDescription entries. Append( currentEntry ); } + /** + * \brief Adds new entry enumeration of type \e EntryType. + * + * Adds new option of setting an entry value. + * \tparam EntryType Type of the entry enumeration. + * \param entryEnum Value of the entry enumeration. + */ template< typename EntryType > void addEntryEnum( const EntryType& entryEnum ) { @@ -139,18 +146,34 @@ class ConfigDescription ( ( ConfigEntry< EntryType >* ) currentEntry )->getEnumValues().Append( entryEnum ); } + /** + * \brief Adds new entry enumeration of type \e char. + * + * Adds new option of setting an entry value. + * \param entryEnum Value of the entry enumeration. + */ void addEntryEnum( const char* entryEnum ) { TNL_ASSERT( this->currentEntry,); ( ( ConfigEntry< String >* ) currentEntry )->getEnumValues().Append( String( entryEnum ) ); } + /** + * \brief Adds delimeter/section to the configuration description. + * + * \param delimeter String that defines how the delimeter looks like. + */ void addDelimiter( const String& delimiter ) { entries.Append( new ConfigDelimiter( delimiter ) ); currentEntry = 0; } + /** + * \brief Gets entry out of the configuration description. + * + * \param name Name of the entry. + */ const ConfigEntryBase* getEntry( const String& name ) const { for( int i = 0; i < entries.getSize(); i++ ) @@ -195,7 +218,13 @@ class ConfigDescription return NULL; } - //! If there is missing entry with defined default value in the Config::ParameterContainer it is going to be added + /** + * \brief Fills in the parameters from the \e parameter_container. + * + * Parameters which were not defined in the command line by user but have their default value are added to the congiguration description. + * If there is missing entry with defined default value in the Config::ParameterContainer it is going to be added. + * \param parameter_container Name of the ParameterContainer object. + */ void addMissingEntries( Config::ParameterContainer& parameter_container ) const; //! Check for all entries with the flag 'required'. @@ -205,6 +234,11 @@ class ConfigDescription bool printUsage, const char* programName ) const; + /** + * \brief Prints configuration description with the \e program_name at the top. + * + * \param program_name Name of the program + */ void printUsage( const char* program_name ) const; //bool parseConfigDescription( const char* file_name ); diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index bcbeaca28..a2e01ea8e 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -85,7 +85,7 @@ class Timer /// \brief Writes a record into the \e logger. /// - /// \param logger + /// \param logger Name of Logger object. /// \param logLevel A non-negative integer recording the log record indent. bool writeLog( Logger& logger, int logLevel = 0 ) const; -- GitLab From 119de82f6f8cd36fba3a0fed13efdb86aa7ca6bd Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Wed, 5 Dec 2018 15:55:59 +0100 Subject: [PATCH 049/111] Added LoggerExample. --- src/Examples/CMakeLists.txt | 6 ++++++ src/Examples/ConfigDescriptionExample.cpp | 11 +++++++++++ src/Examples/LoggerExample.cpp | 23 +++++++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 src/Examples/ConfigDescriptionExample.cpp create mode 100644 src/Examples/LoggerExample.cpp diff --git a/src/Examples/CMakeLists.txt b/src/Examples/CMakeLists.txt index b8e7c574a..235f86021 100644 --- a/src/Examples/CMakeLists.txt +++ b/src/Examples/CMakeLists.txt @@ -18,9 +18,15 @@ add_subdirectory( flow-vl ) #add_subdirectory( fast-sweeping-map ) #add_subdirectory( narrow-band ) +ADD_EXECUTABLE( ConfigDescriptionExample ConfigDescriptionExample.cpp ) +target_link_libraries( ConfigDescriptionExample tnl ) + ADD_EXECUTABLE( FileExample FileExample.cpp ) target_link_libraries( FileExample tnl ) +ADD_EXECUTABLE( LoggerExample LoggerExample.cpp ) +target_link_libraries( LoggerExample tnl ) + ADD_EXECUTABLE( StringExample StringExample.cpp ) target_link_libraries( StringExample tnl ) diff --git a/src/Examples/ConfigDescriptionExample.cpp b/src/Examples/ConfigDescriptionExample.cpp new file mode 100644 index 000000000..56f3e9545 --- /dev/null +++ b/src/Examples/ConfigDescriptionExample.cpp @@ -0,0 +1,11 @@ +#include +#include + +using namespace TNL; +using namespace std; + +int main() +{ + ConfigDescription confd; + +} diff --git a/src/Examples/LoggerExample.cpp b/src/Examples/LoggerExample.cpp new file mode 100644 index 000000000..9624502a2 --- /dev/null +++ b/src/Examples/LoggerExample.cpp @@ -0,0 +1,23 @@ +#include +#include +#include + +using namespace TNL; +using namespace std; + +int main() +{ + Logger logger(50,stream); + + Config::ParameterContainer parameters; + logger.writeSystemInformation(parameters); + + logger.writeHeader("MyTitle"); + parameters.template addParameter< String >( "Device:", "cuda" ); + parameters.template addParameter< String >( "Real type:", "double" ); + parameters.template addParameter< String >( "Index type:", "int" ); + logger.writeSeparator(); + logger.writeSystemInformation(parameters); + logger.writeSeparator(); +} + -- GitLab From 0bafd8d939245098c97ed10674331819307b96f2 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Wed, 5 Dec 2018 17:07:43 +0100 Subject: [PATCH 050/111] Added ListExample and ConfigDescriptionExample. --- src/Examples/CMakeLists.txt | 3 +++ src/Examples/ConfigDescriptionExample.cpp | 5 ++++- src/Examples/ListExample.cpp | 11 +++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/Examples/ListExample.cpp diff --git a/src/Examples/CMakeLists.txt b/src/Examples/CMakeLists.txt index 235f86021..2375c6693 100644 --- a/src/Examples/CMakeLists.txt +++ b/src/Examples/CMakeLists.txt @@ -24,6 +24,9 @@ target_link_libraries( ConfigDescriptionExample tnl ) ADD_EXECUTABLE( FileExample FileExample.cpp ) target_link_libraries( FileExample tnl ) +ADD_EXECUTABLE( ListExample ListExample.cpp ) +target_link_libraries( ListExample tnl ) + ADD_EXECUTABLE( LoggerExample LoggerExample.cpp ) target_link_libraries( LoggerExample tnl ) diff --git a/src/Examples/ConfigDescriptionExample.cpp b/src/Examples/ConfigDescriptionExample.cpp index 56f3e9545..a6e0bded8 100644 --- a/src/Examples/ConfigDescriptionExample.cpp +++ b/src/Examples/ConfigDescriptionExample.cpp @@ -7,5 +7,8 @@ using namespace std; int main() { ConfigDescription confd; - + confd.template addEntry< String >("--new-entry","Specific description."); + confd.template addEntryEnum< String >("option1"); + confd.template addEntryEnum< String >("option2"); + confd.addDelimiter("-----------------------------"); } diff --git a/src/Examples/ListExample.cpp b/src/Examples/ListExample.cpp new file mode 100644 index 000000000..4582436a4 --- /dev/null +++ b/src/Examples/ListExample.cpp @@ -0,0 +1,11 @@ +#include +#include + +using namespace TNL; +using namespace std; + +int main() +{ + List lst; + lst.Append(data); +} \ No newline at end of file -- GitLab From 2ef34bca50475079be5dff2488a92b71185531d6 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Thu, 6 Dec 2018 14:01:46 +0100 Subject: [PATCH 051/111] Added ListExample. --- src/Examples/CMakeLists.txt | 4 ++++ src/Examples/ConfigDescriptionExample.cpp | 2 +- src/Examples/ListExample.cpp | 14 +++++++++++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/Examples/CMakeLists.txt b/src/Examples/CMakeLists.txt index 2375c6693..25fad5b45 100644 --- a/src/Examples/CMakeLists.txt +++ b/src/Examples/CMakeLists.txt @@ -30,6 +30,10 @@ target_link_libraries( ListExample tnl ) ADD_EXECUTABLE( LoggerExample LoggerExample.cpp ) target_link_libraries( LoggerExample tnl ) +ADD_EXECUTABLE( MathExample MathExample.cpp ) +target_link_libraries( MathExample tnl ) + + ADD_EXECUTABLE( StringExample StringExample.cpp ) target_link_libraries( StringExample tnl ) diff --git a/src/Examples/ConfigDescriptionExample.cpp b/src/Examples/ConfigDescriptionExample.cpp index a6e0bded8..6d7d48d90 100644 --- a/src/Examples/ConfigDescriptionExample.cpp +++ b/src/Examples/ConfigDescriptionExample.cpp @@ -1,5 +1,5 @@ #include -#include +#include using namespace TNL; using namespace std; diff --git a/src/Examples/ListExample.cpp b/src/Examples/ListExample.cpp index 4582436a4..8737060d2 100644 --- a/src/Examples/ListExample.cpp +++ b/src/Examples/ListExample.cpp @@ -6,6 +6,18 @@ using namespace std; int main() { + template List< int > lst; List lst; - lst.Append(data); + lst.isEmpty(); + + lst.Append(1); + lst.Append(3); + + lst.isEmpty(); + lst.getSize(); + + lst.Insert(2,1); + + Array array; + lst.template toArray< int >(array); } \ No newline at end of file -- GitLab From b909da5ad1474ffb52a00fb1ed880ea4d9d2c17d Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Thu, 6 Dec 2018 14:58:37 +0100 Subject: [PATCH 052/111] Improved Object documentation. --- src/Examples/MathExample.cpp | 11 +++++++++++ src/TNL/Object.h | 15 +++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/Examples/MathExample.cpp diff --git a/src/Examples/MathExample.cpp b/src/Examples/MathExample.cpp new file mode 100644 index 000000000..4e8db0931 --- /dev/null +++ b/src/Examples/MathExample.cpp @@ -0,0 +1,11 @@ +#include +#include + +using namespace TNL; +using namespace std; + +int main() +{ + isPow2(1024); + roundUpDevision(10,4); +} \ No newline at end of file diff --git a/src/TNL/Object.h b/src/TNL/Object.h index 9725d1db5..405bcd76d 100644 --- a/src/TNL/Object.h +++ b/src/TNL/Object.h @@ -74,10 +74,25 @@ class Object */ virtual bool boundLoad( File& file ); + /** + * \brief Method for saving the object to a file as a binary data. + * + * \param fileName String defining the name of a file. + */ bool save( const String& fileName ) const; + /** + * \brief Method for restoring the object from a file. + * + * \param fileName String defining the name of a file. + */ bool load( const String& fileName ); + /** + * \brief Method for restoring the object from a file. + * + * \param fileName String defining the name of a file. + */ bool boundLoad( const String& fileName ); /// Destructor. -- GitLab From 97ad3fc164606cc285eec288812fb5e3c6248d44 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Fri, 7 Dec 2018 16:54:09 +0100 Subject: [PATCH 053/111] Strarted with Array documentation. --- src/TNL/Containers/Array.h | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/src/TNL/Containers/Array.h b/src/TNL/Containers/Array.h index 5605f7a9c..5186cca6b 100644 --- a/src/TNL/Containers/Array.h +++ b/src/TNL/Containers/Array.h @@ -36,17 +36,38 @@ class Array : public Object typedef Containers::Array< Value, Devices::Host, Index > HostType; typedef Containers::Array< Value, Devices::Cuda, Index > CudaType; + /** \brief Basic constructor. */ Array(); + /** + * \brief Constructor with size. + * + * \param size Number of array elements. / Size of allocated memory. + */ Array( const IndexType& size ); + /** + * \brief Constructor with data and size. + * + * \param data + * \param size Number of array elements. + */ Array( Value* data, const IndexType& size ); + /** + * \brief Copy constructor. + * + * Copies \e size elements from existing \e array into a new array. + * \param array Existing array that is about to be copied. + * \param begin Index from which the array is copied. + * \param size Number of array elements that should be copied. + */ Array( Array& array, const IndexType& begin = 0, const IndexType& size = 0 ); + /** \brief Returns type of string - String. */ static String getType(); virtual String getTypeVirtual() const; @@ -56,14 +77,24 @@ class Array : public Object virtual String getSerializationTypeVirtual() const; /**** - * This sets size of the array. If the array shares data with other arrays - * these data are released. If the current data are not shared and the current - * size is the same as the new one, nothing happens. + * \brief Method for setting the size of an array. + * + * If the array shares data with other arrays these data are released. + * If the current data are not shared and the current size is the same + * as the new one, nothing happens. + * + * \param size Number of array elements. */ void setSize( Index size ); __cuda_callable__ Index getSize() const; + /** + * \brief Assigns features of the existing \e array to the given array. + * + * \tparam ArrayT Type of array. + * \param array Existing array. + */ template< typename ArrayT > void setLike( const ArrayT& array ); -- GitLab From 5b92a5ec6d67d233c5a63c7ce7b4fd18b43cfe37 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 10 Dec 2018 17:03:01 +0100 Subject: [PATCH 054/111] Continued in Array documentation. --- src/TNL/Containers/Array.h | 42 ++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/src/TNL/Containers/Array.h b/src/TNL/Containers/Array.h index 5186cca6b..9a84d9827 100644 --- a/src/TNL/Containers/Array.h +++ b/src/TNL/Containers/Array.h @@ -19,9 +19,8 @@ namespace Containers { template< int, typename > class StaticArray; -/**** +/** * Array handles memory allocation and sharing of the same data between more Arrays. - * */ template< typename Value, typename Device = Devices::Host, @@ -111,14 +110,30 @@ class Array : public Object void swap( Array& array ); + /** + * \brief Resets the given array. + * + * Releases all data from array. + */ void reset(); __cuda_callable__ const Value* getData() const; __cuda_callable__ Value* getData(); + /** + * \brief Sets the value \e x of the array element at position \e i. + * + * \param i Index position. + * \param x New value of an element. + */ void setElement( const Index& i, const Value& x ); + /** + * \brief Accesses specified element at the position \e i. + * + * \param i Index position of an element. + */ Value getElement( const Index& i ) const; __cuda_callable__ inline Value& operator[] ( const Index& i ); @@ -138,25 +153,34 @@ class Array : public Object void setValue( const Value& v ); - // Checks if there is an element with value v in this array + /** + * Checks if there is an element with value v in this array + */ bool containsValue( const Value& v ) const; - // Checks if all elements in this array have the same value v + /** + * Checks if all elements in this array have the same value v + */ bool containsOnlyValue( const Value& v ) const; - /*! + /** * Returns true if non-zero size is set. */ operator bool() const; - //! Method for saving the object to a file as a binary data. + /** + * \brief Method for saving the object to a \e file as a binary data. + */ bool save( File& file ) const; - //! Method for loading the object from a file as a binary data. + /** + * Method for loading the object from a file as a binary data. + */ bool load( File& file ); - //! This method loads data without reallocation. - /**** + /** + * \brief This method loads data without reallocation. + * * This is useful for loading data into shared arrays. * If the array was not initialize yet, common load is * performed. Otherwise, the array size must fit with -- GitLab From 6412bea4af8a3cb6255df0229da353c9e1230fea Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Tue, 11 Dec 2018 15:31:38 +0100 Subject: [PATCH 055/111] Added to Array documentation. --- src/Examples/CMakeLists.txt | 6 +++ src/TNL/Containers/Array.h | 84 ++++++++++++++++++++++++++++--------- 2 files changed, 71 insertions(+), 19 deletions(-) diff --git a/src/Examples/CMakeLists.txt b/src/Examples/CMakeLists.txt index 25fad5b45..4e787076c 100644 --- a/src/Examples/CMakeLists.txt +++ b/src/Examples/CMakeLists.txt @@ -37,5 +37,11 @@ target_link_libraries( MathExample tnl ) ADD_EXECUTABLE( StringExample StringExample.cpp ) target_link_libraries( StringExample tnl ) +ADD_EXECUTABLE( StringExampleGetSize StringExampleGetSize.cpp ) +target_link_libraries( StringExampleGetSize tnl ) + +ADD_EXECUTABLE( StringExampleGetAllocatedSize StringExampleGetAllocatedSize.cpp ) +target_link_libraries( StringExampleGetAllocatedSize tnl ) + ADD_EXECUTABLE( TimerExample TimerExample.cpp ) target_link_libraries( TimerExample tnl ) \ No newline at end of file diff --git a/src/TNL/Containers/Array.h b/src/TNL/Containers/Array.h index 9a84d9827..8d43a979b 100644 --- a/src/TNL/Containers/Array.h +++ b/src/TNL/Containers/Array.h @@ -66,16 +66,19 @@ class Array : public Object const IndexType& begin = 0, const IndexType& size = 0 ); - /** \brief Returns type of string - String. */ + /** \brief Returns type of array value, device type and the type of index. */ static String getType(); + /** \brief Returns type of array value, device type and the type of index. */ virtual String getTypeVirtual() const; + /** \brief Returns (host) type of array value, device type and the type of index. */ static String getSerializationType(); + /** \brief Returns (host) type of array value, device type and the type of index. */ virtual String getSerializationTypeVirtual() const; - /**** + /** * \brief Method for setting the size of an array. * * If the array shares data with other arrays these data are released. @@ -86,11 +89,13 @@ class Array : public Object */ void setSize( Index size ); + /** \brief Method for getting the size of an array. */ __cuda_callable__ Index getSize() const; /** * \brief Assigns features of the existing \e array to the given array. * + * Sets the same size as the size of existing \e array. * \tparam ArrayT Type of array. * \param array Existing array. */ @@ -108,6 +113,13 @@ class Array : public Object template< int Size > void bind( StaticArray< Size, Value >& array ); + /** + * \brief Swaps all features of given array with existing \e array. + * + * Swaps sizes, all values (data), allocated memory and references of given + * array with existing array. + * \param array Existing array, which features are swaped with given array. + */ void swap( Array& array ); /** @@ -117,12 +129,18 @@ class Array : public Object */ void reset(); + /** + * \brief Method for getting the data from given array with constant poiner. + */ __cuda_callable__ const Value* getData() const; + /** + * \brief Method for getting the data from given array. + */ __cuda_callable__ Value* getData(); /** - * \brief Sets the value \e x of the array element at position \e i. + * \brief Assignes the value \e x to the array element at position \e i. * * \param i Index position. * \param x New value of an element. @@ -130,14 +148,24 @@ class Array : public Object void setElement( const Index& i, const Value& x ); /** - * \brief Accesses specified element at the position \e i. + * \brief Accesses specified element at the position \e i and returns its value. * * \param i Index position of an element. */ Value getElement( const Index& i ) const; + /** + * \brief Accesses specified element at the position \e i and returns a reference to its value. + * + * \param i Index position of an element. + */ __cuda_callable__ inline Value& operator[] ( const Index& i ); + /** + * \brief Accesses specified element at the position \e i and returns a (constant?) reference to its value. + * + * \param i Index position of an element. + */ __cuda_callable__ inline const Value& operator[] ( const Index& i ) const; Array& operator = ( const Array& array ); @@ -151,30 +179,43 @@ class Array : public Object template< typename ArrayT > bool operator != ( const ArrayT& array ) const; + /** + * \brief + * + * \param v Reference to a value. + */ void setValue( const Value& v ); /** - * Checks if there is an element with value v in this array + * \brief Checks if there is an element with value \e v in given array. + * + * \param v Reference to a value. */ bool containsValue( const Value& v ) const; /** - * Checks if all elements in this array have the same value v + * \brief Checks if all elements in given array have the same value \e v. + * + * \param v Reference to a value. */ bool containsOnlyValue( const Value& v ) const; /** - * Returns true if non-zero size is set. + * \brief Returns true if non-zero size is set. */ operator bool() const; /** * \brief Method for saving the object to a \e file as a binary data. + * + * \param file Reference to a file. */ bool save( File& file ) const; /** * Method for loading the object from a file as a binary data. + * + * \param file Reference to a file. */ bool load( File& file ); @@ -194,31 +235,36 @@ class Array : public Object using Object::boundLoad; + /** \brief Basic destructor. */ ~Array(); protected: + /** \brief Method for releasing array data. */ void releaseData() const; - //!Number of elements in array + /** \brief Number of elements in array. */ mutable Index size; - //! Pointer to data + /** \brief Pointer to data. */ mutable Value* data; - /**** - * Pointer to the originally allocated data. They might differ if one - * long array is partitioned into more shorter arrays. Each of them - * must know the pointer on allocated data because the last one must - * deallocate the array. If outer data (not allocated by TNL) are bind - * then this pointer is zero since no deallocation is necessary. + /** + * \brief Pointer to the originally allocated data. + * + * They might differ if one long array is partitioned into more shorter + * arrays. Each of them must know the pointer on allocated data because + * the last one must deallocate the array. If outer data (not allocated + * by TNL) are bind then this pointer is zero since no deallocation is + * necessary. */ mutable Value* allocationPointer; - /**** - * Counter of objects sharing this array or some parts of it. The reference counter is - * allocated after first sharing of the data between more arrays. This is to avoid - * unnecessary dynamic memory allocation. + /** + * \brief Counter of objects sharing this array or some parts of it. + * + * The reference counter is allocated after first sharing of the data + * between more arrays. This is to avoid unnecessary dynamic memory allocation. */ mutable int* referenceCounter; }; -- GitLab From 10863b85408b3e1dfd627fb6423905d9c02c0a3b Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Tue, 2 Oct 2018 16:11:31 +0200 Subject: [PATCH 056/111] Added comment to String constructor. --- src/TNL/String.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/TNL/String.h b/src/TNL/String.h index f5657a20f..e8859c996 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -41,10 +41,11 @@ public: //! Constructor from const char* String( const char* str ); - //! Constructor with char pointer - /*! @param prefix_cut_off says length of the prefix that is going to be omitted and - @param sufix_cut_off says the same about sufix. - */ + ////// + /// Constructor with char pointer + /// + /// @param prefix_cut_off says length of the prefix that is going to be omitted and + /// @param sufix_cut_off says the same about sufix. String( const char* c, int prefix_cut_off, int sufix_cut_off = 0 ); -- GitLab From 097bcc0b71d6ea87beacce8eb896bf39d6edfca2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Oberhuber?= Date: Wed, 3 Oct 2018 21:25:02 +0200 Subject: [PATCH 057/111] Tunning comments in String.h. --- src/TNL/String.h | 260 +++++++++++++++++++++++------------------------ 1 file changed, 127 insertions(+), 133 deletions(-) diff --git a/src/TNL/String.h b/src/TNL/String.h index e8859c996..2d3d89af9 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -25,141 +25,135 @@ class String; template< typename T > String convertToString( const T& value ); -//! Class for managing strings +///// +// \brief Class for managing strings class String { - //! Pointer to char ended with zero - char* string; - - //! Length of the allocated piece of memory - int length; - -public: - //! Basic constructor - String(); - - //! Constructor from const char* - String( const char* str ); - - ////// - /// Constructor with char pointer - /// - /// @param prefix_cut_off says length of the prefix that is going to be omitted and - /// @param sufix_cut_off says the same about sufix. - String( const char* c, - int prefix_cut_off, - int sufix_cut_off = 0 ); - - //! Copy constructor - String( const String& str ); - - ////// - /// Templated constructor - /// - /// It must be explicit otherwise it is called recursively from inside of its - /// definition ( in operator << ). It leads to stack overflow and segmentation fault. - template< typename T > - explicit - String( const T& value ) - : string( nullptr ), length( 0 ) - { - std::stringstream str; - str << value; - setString( str.str().data() ); - } - - String( const bool b ); - - //! Destructor - ~String(); - - static String getType(); - - //! Return length of the string - int getLength() const; - int getSize() const; - - //! Return currently allocated size - int getAllocatedSize() const; - - //! Reserve space for given number of characters - void setSize( int size ); - - //! Set string from given char pointer - /*! @param prefix_cut_off says length of the prefix that is going to be omitted and - @param sufix_cut_off says the same about sufix. - */ - void setString( const char* c, - int prefix_cut_off = 0, - int sufix_cut_off = 0 ); - - //! Return pointer to data - const char* getString() const; - - //! Return pointer to data - char* getString(); - - //! Operator for accesing particular chars of the string - const char& operator[]( int i ) const; - - //! Operator for accesing particular chars of the string - char& operator[]( int i ); - - /**** - * Operators for C strings - */ - String& operator=( const char* str ); - String& operator+=( const char* str ); - String operator+( const char* str ) const; - bool operator==( const char* str ) const; - bool operator!=( const char* str ) const; - - /**** - * Operators for Strings - */ - String& operator=( const String& str ); - String& operator+=( const String& str ); - String operator+( const String& str ) const; - bool operator==( const String& str ) const; - bool operator!=( const String& str ) const; - - /**** - * Operators for single characters - */ - String& operator=( char str ); - String& operator+=( char str ); - String operator+( char str ) const; - bool operator==( char str ) const; - bool operator!=( char str ) const; - - //! Cast to bool operator - operator bool() const; - - //! Cast to bool with negation operator - bool operator!() const; - - String replace( const String& pattern, - const String& replaceWith, - int count = 0 ) const; - - String strip( char strip = ' ' ) const; - - //! Split the string into list of strings w.r.t. given separator. - int split( Containers::List< String >& list, const char separator = ' ' ) const; - - //! Write to a binary file - bool save( File& file ) const; - - //! Read from binary file - bool load( File& file ); - - //! Broadcast to other nodes in MPI cluster -// void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); - - //! Read one line from given stream. - bool getLine( std::istream& stream ); - - friend std::ostream& operator<<( std::ostream& stream, const String& str ); + public: + + ///// + /// \brief Basic constructor + String(); + + ///// + /// \brief Constructor with char pointer. + /// Constructor with char pointer. + /// @param prefix_cut_off says length of the prefix that is going to be omitted and + /// @param sufix_cut_off says the same about suffix. + String( const char* c, + int prefix_cut_off = 0, + int sufix_cut_off = 0 ); + + static String getType(); + + //! Copy constructor + String( const String& str ); + + //! Convert anything to a string + template< typename T > + explicit + String( T value ) + : string( nullptr ), length( 0 ) + { + setString( convertToString( value ).getString() ); + } + + //! Destructor + ~String(); + + //! Return length of the string + int getLength() const; + int getSize() const; + + //! Return currently allocated size + int getAllocatedSize() const; + + //! Reserve space for given number of characters + void setSize( int size ); + + //! Set string from given char pointer + /*! @param prefix_cut_off says length of the prefix that is going to be omitted and + @param sufix_cut_off says the same about sufix. + */ + void setString( const char* c, + int prefix_cut_off = 0, + int sufix_cut_off = 0 ); + + //! Return pointer to data + const char* getString() const; + + //! Return pointer to data + char* getString(); + + //! Operator for accesing particular chars of the string + const char& operator[]( int i ) const; + + //! Operator for accesing particular chars of the string + char& operator[]( int i ); + + /**** + * Operators for C strings + */ + String& operator=( const char* str ); + String& operator+=( const char* str ); + String operator+( const char* str ) const; + bool operator==( const char* str ) const; + bool operator!=( const char* str ) const; + + /**** + * Operators for Strings + */ + String& operator=( const String& str ); + String& operator+=( const String& str ); + String operator+( const String& str ) const; + bool operator==( const String& str ) const; + bool operator!=( const String& str ) const; + + /**** + * Operators for single characters + */ + String& operator=( char str ); + String& operator+=( char str ); + String operator+( char str ) const; + bool operator==( char str ) const; + bool operator!=( char str ) const; + + //! Cast to bool operator + operator bool() const; + + //! Cast to bool with negation operator + bool operator!() const; + + String replace( const String& pattern, + const String& replaceWith, + int count = 0 ) const; + + String strip( char strip = ' ' ) const; + + //! Split the string into list of strings w.r.t. given separator. + int split( Containers::List< String >& list, const char separator = ' ' ) const; + + //! Write to a binary file + bool save( File& file ) const; + + //! Read from binary file + bool load( File& file ); + + //! Broadcast to other nodes in MPI cluster + // void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); + + //! Read one line from given stream. + bool getLine( std::istream& stream ); + + friend std::ostream& operator<<( std::ostream& stream, const String& str ); + + protected: + //! Pointer to char ended with zero + char* string; + + //! Length of the allocated piece of memory + int length; + }; String operator+( char string1, const String& string2 ); -- GitLab From e3d4c8be55f5ce2328ee37acd483399d74e617a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Oberhuber?= Date: Sun, 7 Oct 2018 18:33:10 +0200 Subject: [PATCH 058/111] Deleted Doxyfile in src/TNL. --- src/TNL/Doxyfile | 1514 ---------------------------------------------- 1 file changed, 1514 deletions(-) delete mode 100644 src/TNL/Doxyfile diff --git a/src/TNL/Doxyfile b/src/TNL/Doxyfile deleted file mode 100644 index 4fb5d22f9..000000000 --- a/src/TNL/Doxyfile +++ /dev/null @@ -1,1514 +0,0 @@ -# Doxyfile 1.6.1 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = tnl - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = ../Release/src - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = YES - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# 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 = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = - -# 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 = - -# 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. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = NO - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 3 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it parses. -# With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this tag. -# The format is ext=language, where ext is a file extension, and language is one of -# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, -# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat -# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), -# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. - -EXTENSION_MAPPING = - -# 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 = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen to replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. - -TYPEDEF_HIDES_STRUCT = NO - -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penality. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will rougly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols - -SYMBOL_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespace are hidden. - -EXTRACT_ANON_NSPACES = NO - -# 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 = NO - -# 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 = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# 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 = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = 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. - -SHOW_DIRECTORIES = NO - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by -# doxygen. The layout file controls the global structure of the generated output files -# in an output format independent way. The create the layout file that represents -# doxygen's defaults, run doxygen with the -l option. You can optionally specify a -# file name after the option, if omitted DoxygenLayout.xml will be used as the name -# of the layout file. - -LAYOUT_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# 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 = - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 - -FILE_PATTERNS = - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# 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 = - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# 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 = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# 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 = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. - -REFERENCES_LINK_SOURCE = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = NO - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# 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. - -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. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = NO - -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. - -GENERATE_DOCSET = NO - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. - -CHM_INDEX_ENCODING = - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER -# are set, an additional index file will be generated that can be used as input for -# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated -# HTML documentation. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace - -QHP_NAMESPACE = - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders - -QHP_VIRTUAL_FOLDER = doc - -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. -# For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see -# Qt Help Project / Custom Filters. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's -# filter section matches. -# Qt Help Project / Filter Attributes. - -QHP_SECT_FILTER_ATTRS = - -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. - -QHG_LOCATION = - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. - -GENERATE_TREEVIEW = NO - -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. - -USE_INLINE_TREES = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. - -FORMULA_FONTSIZE = 10 - -# When the SEARCHENGINE tag is enable doxygen will generate a search box for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP) or Qt help (GENERATE_QHP) -# there is already a search function so this one should typically -# be disabled. - -SEARCHENGINE = YES - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = YES - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = YES - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = YES - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -# If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER. - -LATEX_SOURCE_CODE = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. -# This is useful -# if you want to understand what is going on. -# On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# 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 = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more -# powerful graphs. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = NO - -# By default doxygen will write a font called FreeSans.ttf to the output -# directory and reference it in all dot files that doxygen generates. This -# font does not include all possible unicode characters however, so when you need -# these (or just want a differently looking font) you can specify the font name -# using DOT_FONTNAME. You need need to make sure dot is able to find the font, -# which can be done by putting it in a standard location or by setting the -# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory -# containing the font. - -DOT_FONTNAME = FreeSans - -# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. -# The default size is 10pt. - -DOT_FONTSIZE = 10 - -# By default doxygen will tell dot to use the output directory to look for the -# FreeSans.ttf font (which doxygen will put there itself). If you specify a -# different font using DOT_FONTNAME you can set the path where dot -# can find it using this tag. - -DOT_FONTPATH = - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = NO - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. - -CALLER_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of -# a graph (i.e. they become hard to read). - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = YES - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES -- GitLab From 67b1142b8694562795cb8d17693951b30a305ecd Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber Date: Wed, 17 Oct 2018 15:17:21 +0200 Subject: [PATCH 059/111] Added string test getLine. --- src/UnitTests/StringTest.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/UnitTests/StringTest.cpp b/src/UnitTests/StringTest.cpp index 665145558..dcf500796 100644 --- a/src/UnitTests/StringTest.cpp +++ b/src/UnitTests/StringTest.cpp @@ -284,6 +284,23 @@ TEST( StringTest, SaveLoad ) EXPECT_EQ( std::remove( "test-file.tnl" ), 0 ); }; + +TEST( StringTest, getLine ) +{ + std::stringstream str; + str << "Line 1" << std::endl; + str << "Line 2" << std::endl; + str.seekg( 0 ); + + String s; + + s.getLine( str ); + EXPECT_EQ( s, "Line 1" ); + + s.getLine( str ); + EXPECT_EQ( s, "Line 2" ); +}; + #endif -- GitLab From 574c256c4b58a0b71ef0e0ea919fd0c25560a77a Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber Date: Wed, 17 Oct 2018 15:44:02 +0200 Subject: [PATCH 060/111] Added FileNameTest. --- src/UnitTests/CMakeLists.txt | 12 ++++----- src/UnitTests/FileNameTest.cpp | 47 ++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 src/UnitTests/FileNameTest.cpp diff --git a/src/UnitTests/CMakeLists.txt b/src/UnitTests/CMakeLists.txt index 842ce9f2c..cf0fc8c47 100644 --- a/src/UnitTests/CMakeLists.txt +++ b/src/UnitTests/CMakeLists.txt @@ -31,17 +31,17 @@ else() tnl ) endif() +ADD_EXECUTABLE( FileNameTest FileNameTest.cpp ) +TARGET_COMPILE_OPTIONS( FileNameTest PRIVATE ${CXX_TESTS_FLAGS} ) +TARGET_LINK_LIBRARIES( FileNameTest ${GTEST_BOTH_LIBRARIES} tnl ) + ADD_EXECUTABLE( StringTest StringTest.cpp ) TARGET_COMPILE_OPTIONS( StringTest PRIVATE ${CXX_TESTS_FLAGS} ) -TARGET_LINK_LIBRARIES( StringTest - ${GTEST_BOTH_LIBRARIES} - tnl ) +TARGET_LINK_LIBRARIES( StringTest ${GTEST_BOTH_LIBRARIES} tnl ) ADD_EXECUTABLE( ObjectTest ObjectTest.cpp ) TARGET_COMPILE_OPTIONS( ObjectTest PRIVATE ${CXX_TESTS_FLAGS} ) -TARGET_LINK_LIBRARIES( ObjectTest - ${GTEST_BOTH_LIBRARIES} - tnl ) +TARGET_LINK_LIBRARIES( ObjectTest ${GTEST_BOTH_LIBRARIES} tnl ) ADD_EXECUTABLE( SaveAndLoadMeshfunctionTest SaveAndLoadMeshfunctionTest.cpp ) TARGET_COMPILE_OPTIONS( SaveAndLoadMeshfunctionTest PRIVATE ${CXX_TESTS_FLAGS} ) diff --git a/src/UnitTests/FileNameTest.cpp b/src/UnitTests/FileNameTest.cpp new file mode 100644 index 000000000..3f71be146 --- /dev/null +++ b/src/UnitTests/FileNameTest.cpp @@ -0,0 +1,47 @@ +/*************************************************************************** + FileNameTest.cpp - description + ------------------- + begin : Oct 17, 2018 + copyright : (C) 2018 by Tomas Oberhuber + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by Nina Dzugasova + +#ifdef HAVE_GTEST +#include +#endif + +#include + +using namespace TNL; + +#ifdef HAVE_GTEST +TEST( FileNameTest, Constructor ) +{ + /*String str1( "string1" ); + String str2( "xxxstring2", 3 ); + String str3( "string3xxx", 0, 3 ); + String str4( "xxxstring4xxx", 3, 3 ); + + EXPECT_EQ( strcmp( str1.getString(), "string1" ), 0 ); + EXPECT_EQ( strcmp( str2.getString(), "string2" ), 0 ); + EXPECT_EQ( strcmp( str3.getString(), "string3" ), 0 ); + EXPECT_EQ( strcmp( str4.getString(), "string4" ), 0 );*/ +} +#endif + + +#include "GtestMissingError.h" +int main( int argc, char* argv[] ) +{ +#ifdef HAVE_GTEST + ::testing::InitGoogleTest( &argc, argv ); + return RUN_ALL_TESTS(); +#else + throw GtestMissingError(); +#endif +} + -- GitLab From b3de486905e3a5e8c562db8a5c6984d545a1099f Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Wed, 17 Oct 2018 16:18:58 +0200 Subject: [PATCH 061/111] Added tests(GetSize, GetAllocatedSize, GetString) and modified tests (SetString, replace) in StringTest. --- src/UnitTests/StringTest.cpp | 40 ++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/UnitTests/StringTest.cpp b/src/UnitTests/StringTest.cpp index dcf500796..4c1f1dcc9 100644 --- a/src/UnitTests/StringTest.cpp +++ b/src/UnitTests/StringTest.cpp @@ -62,6 +62,34 @@ TEST( StringTest, ConstructorWithNumber ) EXPECT_EQ( strcmp( string4.getString(), "false" ), 0 ); } +TEST( StringTest, GetSize ) +{ + String str1( "string" ); + String str2( "12345" ); + String str3( "string3" ); + String str4( "String_4" ); + String str5( "Last String" ); + + EXPECT_EQ( str1.getSize(), 6 ); + EXPECT_EQ( str2.getSize(), 5 ); + EXPECT_EQ( str3.getSize(), 7 ); + EXPECT_EQ( str4.getSize(), 8 ); + EXPECT_EQ( str5.getSize(), 11 ); + + EXPECT_EQ( str1.getLength(), 6 ); + EXPECT_EQ( str2.getLength(), 5 ); + EXPECT_EQ( str3.getLength(), 7 ); + EXPECT_EQ( str4.getLength(), 8 ); + EXPECT_EQ( str5.getLength(), 11 ); +} + +TEST( StringTest, GetAllocatedSize ) +{ + String str( "MeineKleine" ); + + EXPECT_EQ( str.getAllocatedSize(), 256 ); +} + TEST( StringTest, SetSize ) { String str; @@ -85,6 +113,15 @@ TEST( StringTest, SetString ) EXPECT_EQ( strcmp( str2.getString(), "string2" ), 0 ); EXPECT_EQ( strcmp( str3.getString(), "string3" ), 0 ); EXPECT_EQ( strcmp( str4.getString(), "string4" ), 0 ); + + str4.setString( "string4_2", 0, 2 ); + EXPECT_EQ( strcmp( str4.getString(), "string4" ), 0 ); +} + +TEST( StringTest, GetString ) +{ + String str( "MyString" ); + EXPECT_EQ( strcmp( str.getString(), "MyString" ), 0 ); } TEST( StringTest, IndexingOperator ) @@ -229,6 +266,9 @@ TEST( StringTest, replace ) EXPECT_EQ( String( "string" ).replace( "ing", "bc" ), "strbc" ); EXPECT_EQ( String( "abracadabra" ).replace( "ab", "CAT" ), "CATracadCATra" ); EXPECT_EQ( String( "abracadabra" ).replace( "ab", "CAT", 1 ), "CATracadabra" ); + EXPECT_NE( String( "abracadabra" ).replace( "ab", "CAT", 2 ), "abracadCATra" ); + EXPECT_NE( String( "abracadabra" ).replace( "ab", "CAT", 2 ), "abracadabra" ); + EXPECT_EQ( String( "abracadabra" ).replace( "ab", "CAT", 2 ), "CATracadCATra" ); } TEST( StringTest, strip ) -- GitLab From e2bbe047e4b18d1957618d70d9081143051c5add Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Fri, 19 Oct 2018 16:44:18 +0200 Subject: [PATCH 062/111] Added documentation of String. Found error in StringTest split function. --- src/TNL/DistributedContainers/Subrange.h | 1 - .../Linear/Preconditioners/Preconditioner.h | 2 + src/TNL/String.h | 101 +++++++++++------- src/UnitTests/StringTest.cpp | 8 ++ 4 files changed, 74 insertions(+), 38 deletions(-) diff --git a/src/TNL/DistributedContainers/Subrange.h b/src/TNL/DistributedContainers/Subrange.h index 1512bd2ee..e581c9a4f 100644 --- a/src/TNL/DistributedContainers/Subrange.h +++ b/src/TNL/DistributedContainers/Subrange.h @@ -13,7 +13,6 @@ #pragma once #include - #include #include #include diff --git a/src/TNL/Solvers/Linear/Preconditioners/Preconditioner.h b/src/TNL/Solvers/Linear/Preconditioners/Preconditioner.h index 8d294bd8a..58ab8c682 100644 --- a/src/TNL/Solvers/Linear/Preconditioners/Preconditioner.h +++ b/src/TNL/Solvers/Linear/Preconditioners/Preconditioner.h @@ -17,6 +17,8 @@ #include #include +#include "../Traits.h" + namespace TNL { namespace Solvers { namespace Linear { diff --git a/src/TNL/String.h b/src/TNL/String.h index 2d3d89af9..b902be675 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -26,30 +26,33 @@ template< typename T > String convertToString( const T& value ); ///// -// \brief Class for managing strings +// \brief Class for managing strings. class String { public: ///// - /// \brief Basic constructor + /// \brief Basic constructor. Constructs an empty string object, with the length of zero characters. String(); ///// /// \brief Constructor with char pointer. - /// Constructor with char pointer. - /// @param prefix_cut_off says length of the prefix that is going to be omitted and - /// @param sufix_cut_off says the same about suffix. + /// Copies the null-terminated character sequence (C-string) pointed by \e c. + /// Constructs a string initialized with the 8-bit string \e c, excluding the given number of \e prefix_cut_off and \e sufix_cut_off characters. + /// @param prefix_cut_off determines the length of the prefix that is going to be omitted from the string \e c + /// @param sufix_cut_off determines the length of the sufix that is going to be omitted from the string \e c String( const char* c, int prefix_cut_off = 0, int sufix_cut_off = 0 ); + /// Returns type of string - String. static String getType(); - //! Copy constructor + ///// + /// \brief Copy constructor. Constructs a copy of the string \e str. String( const String& str ); - //! Convert anything to a string + /// \brief Converts anything to a string. template< typename T > explicit String( T value ) @@ -58,106 +61,130 @@ class String setString( convertToString( value ).getString() ); } - //! Destructor + /// \brief Destructor. ~String(); - //! Return length of the string + /// Returns the number of characters in given string. Equivalent to \c getSize(). int getLength() const; + /// Returns the number of characters in given string. int getSize() const; - //! Return currently allocated size + /// Returns size of allocated storage for given string. int getAllocatedSize() const; - //! Reserve space for given number of characters + /// Reserves space for given number of characters (\e size). + /// Requests to allocate storage for given \e size (number of characters). void setSize( int size ); - //! Set string from given char pointer - /*! @param prefix_cut_off says length of the prefix that is going to be omitted and - @param sufix_cut_off says the same about sufix. - */ + ///// + /// Sets string from given char pointer \e c. + /// @param prefix_cut_off determines the length of the prefix that is going to be omitted from the string \e c + /// @param sufix_cut_off determines the length of the sufix that is going to be omitted from the string \e c void setString( const char* c, int prefix_cut_off = 0, int sufix_cut_off = 0 ); - //! Return pointer to data + /// Returns pointer to data. It returns the content of the given string. const char* getString() const; - //! Return pointer to data + /// Returns pointer to data. char* getString(); - //! Operator for accesing particular chars of the string + /// \brief Operator for accesing particular chars of the string. This function overloads operator[](). It returns a reference to the character at position \e i in given string. const char& operator[]( int i ) const; - //! Operator for accesing particular chars of the string + /// \brief Operator for accesing particular chars of the string. It returns the character at the position \e i in given string as a modifiable reference. char& operator[]( int i ); - /**** - * Operators for C strings - */ + ///// + /// \brief Operators for C strings. + /// This function overloads operator=(). It assigns \e str to this string, replacing its current contents. String& operator=( const char* str ); + /// This function overloads operator+=(). It appends the string \e str to this string. String& operator+=( const char* str ); + /// This function concatenates strings and returns a newly constructed string object. String operator+( const char* str ) const; + /// This function overloads operator==(). bool operator==( const char* str ) const; + /// This function overloads operator!=(). bool operator!=( const char* str ) const; - /**** - * Operators for Strings - */ + ///// + /// \brief Operators for Strings. + /// This function assigns \e str to this string and returns a reference to this string. String& operator=( const String& str ); + /// This function appends the string \e str onto the end of this string and returns a reference to this string. String& operator+=( const String& str ); + /// This function concatenates strings and returns a newly constructed string object. String operator+( const String& str ) const; + /// This function overloads operator==(). It returns \c true if this string is equal to \e str, otherwise returns \c false. bool operator==( const String& str ) const; + /// This function overloads operator!=(). It returns \c true if this string is not equal to \e str, otherwise returns \c false. bool operator!=( const String& str ) const; - /**** - * Operators for single characters - */ + ///// + /// \brief Operators for single characters. + /// This function overloads operator=(). It assigns character /e str to this string. String& operator=( char str ); + /// This function overloads operator+=(). It appends character /e str to this string. String& operator+=( char str ); + // This function concatenates strings and returns a newly constructed string object. String operator+( char str ) const; + // This function concatenates strings and returns a newly constructed string object. bool operator==( char str ) const; + /// This function overloads operator!=(). bool operator!=( char str ) const; - //! Cast to bool operator + /// \brief Cast to bool operator. operator bool() const; - //! Cast to bool with negation operator + /// \brief Cast to bool with negation operator. bool operator!() const; + ///// + /// \brief Replaces portion of string. + ///It replaces section \e pattern from this string with new piece of string \e replaceWith. + ///If parameter \e count is defined, the function makes replacement several times, every time when it finds the same pattern in this string. String replace( const String& pattern, const String& replaceWith, int count = 0 ) const; + /// \brief Trims/strips given string. It removes all spaces from string except for single spaces between words. String strip( char strip = ' ' ) const; - //! Split the string into list of strings w.r.t. given separator. + /// \brief Splits string into list of strings with respect to given \e separator. + /// It splits the string into list of substrings wherever \e separator occurs, and returs list of those strings. + /// When \e separator does not appear anywhere in the given string, this function returns a single-element list containing given sting. + /// @param separator Character, which separates substrings in given string. Empty character can not be used. int split( Containers::List< String >& list, const char separator = ' ' ) const; - //! Write to a binary file + /// Write to a binary file bool save( File& file ) const; - //! Read from binary file + /// Read from binary file bool load( File& file ); //! Broadcast to other nodes in MPI cluster - // void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); + // void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); - //! Read one line from given stream. + /// Read one line from given stream. bool getLine( std::istream& stream ); friend std::ostream& operator<<( std::ostream& stream, const String& str ); protected: - //! Pointer to char ended with zero + /// Pointer to char ended with zero char* string; - //! Length of the allocated piece of memory + /// Length of the allocated piece of memory int length; }; +/// Returns concatenation of \e string1 and \e string2. String operator+( char string1, const String& string2 ); +/// Returns concatenation of \e string1 and \e string2. String operator+( const char* string1, const String& string2 ); std::ostream& operator<<( std::ostream& stream, const String& str ); diff --git a/src/UnitTests/StringTest.cpp b/src/UnitTests/StringTest.cpp index 4c1f1dcc9..f6664673e 100644 --- a/src/UnitTests/StringTest.cpp +++ b/src/UnitTests/StringTest.cpp @@ -308,6 +308,14 @@ TEST( StringTest, split ) String( "abracadabra" ).split( list, 'A' ); ASSERT_EQ( list.getSize(), 1 ); EXPECT_EQ( list[ 0 ], "abracadabra" ); + + /// !!!! + String( "a,,b,c" ).split( list, ',' ); + ASSERT_EQ( list.getSize(), 4 ); + EXPECT_EQ( list[ 0 ], "a" ); + EXPECT_EQ( list[ 1 ], "" ); + EXPECT_EQ( list[ 2 ], "b" ); + EXPECT_EQ( list[ 3 ], "c" ); } TEST( StringTest, SaveLoad ) -- GitLab From bbcfd08d44e641114329ed59bc8aa67b563d41c3 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 22 Oct 2018 16:09:40 +0200 Subject: [PATCH 063/111] Added documentation to String. --- src/TNL/String.h | 17 ++++++++++------- src/UnitTests/StringTest.cpp | 8 +++++++- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/TNL/String.h b/src/TNL/String.h index b902be675..a35b5b91c 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -135,7 +135,7 @@ class String /// This function overloads operator!=(). bool operator!=( char str ) const; - /// \brief Cast to bool operator. + /// \brief Cast to bool operator. Converts string to boolean expression (true or false). operator bool() const; /// \brief Cast to bool with negation operator. @@ -158,25 +158,27 @@ class String /// @param separator Character, which separates substrings in given string. Empty character can not be used. int split( Containers::List< String >& list, const char separator = ' ' ) const; - /// Write to a binary file + /// Writes to a binary file and returns boolean expression based on the success in writing into the file. bool save( File& file ) const; - /// Read from binary file + /// Reads from binary file and returns boolean expression based on the success in reading the file. bool load( File& file ); - //! Broadcast to other nodes in MPI cluster + /// !!! Mozem dat prec??? + // Broadcast to other nodes in MPI cluster // void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); - /// Read one line from given stream. + /// Reads one line from given stream. bool getLine( std::istream& stream ); + ///toto neviem co friend std::ostream& operator<<( std::ostream& stream, const String& str ); protected: - /// Pointer to char ended with zero + /// Pointer to char ended with zero ...Preco? char* string; - /// Length of the allocated piece of memory + /// Length of the allocated piece of memory. int length; }; @@ -187,6 +189,7 @@ String operator+( char string1, const String& string2 ); /// Returns concatenation of \e string1 and \e string2. String operator+( const char* string1, const String& string2 ); +/// Toto neviem co std::ostream& operator<<( std::ostream& stream, const String& str ); template< typename T > diff --git a/src/UnitTests/StringTest.cpp b/src/UnitTests/StringTest.cpp index f6664673e..9b85bd728 100644 --- a/src/UnitTests/StringTest.cpp +++ b/src/UnitTests/StringTest.cpp @@ -309,7 +309,7 @@ TEST( StringTest, split ) ASSERT_EQ( list.getSize(), 1 ); EXPECT_EQ( list[ 0 ], "abracadabra" ); - /// !!!! + /// !!!! ma problem s prazdnym stringom !!!! String( "a,,b,c" ).split( list, ',' ); ASSERT_EQ( list.getSize(), 4 ); EXPECT_EQ( list[ 0 ], "a" ); @@ -349,6 +349,12 @@ TEST( StringTest, getLine ) EXPECT_EQ( s, "Line 2" ); }; +/*TEST( StringTest, OperatorCudny ) +{ + String str("String1"); + EXPECT_EQ(strcmp(String( "a", str ), "aString1"), 0 ); +};*/ + #endif -- GitLab From 8fd5777913c80736a9ea8c7f5410920d6755977e Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Wed, 24 Oct 2018 16:02:57 +0200 Subject: [PATCH 064/111] Altered documentation of String. Started with examples. --- Doxyfile | 2 +- src/TNL/String.h | 177 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 136 insertions(+), 43 deletions(-) diff --git a/Doxyfile b/Doxyfile index a796c7fe3..649e477a4 100644 --- a/Doxyfile +++ b/Doxyfile @@ -906,7 +906,7 @@ EXCLUDE_SYMBOLS = # that contain example code fragments that are included (see the \include # command). -EXAMPLE_PATH = +EXAMPLE_PATH = src/Examples # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and diff --git a/src/TNL/String.h b/src/TNL/String.h index a35b5b91c..056afd3fa 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -36,11 +36,22 @@ class String String(); ///// - /// \brief Constructor with char pointer. + /// \brief Constructor with char pointer. + /// /// Copies the null-terminated character sequence (C-string) pointed by \e c. - /// Constructs a string initialized with the 8-bit string \e c, excluding the given number of \e prefix_cut_off and \e sufix_cut_off characters. - /// @param prefix_cut_off determines the length of the prefix that is going to be omitted from the string \e c - /// @param sufix_cut_off determines the length of the sufix that is going to be omitted from the string \e c + /// Constructs a string initialized with the 8-bit string \e c, excluding + /// the given number of \e prefix_cut_off and \e sufix_cut_off characters. + /// + /// @param prefix_cut_off Determines the length of the prefix that is going + /// to be omitted from the string \e c. + /// @param sufix_cut_off Determines the length of the sufix that is going + /// to be omitted from the string \e c. + /// + /// \par Example + /// \code String str( "xxstringxxx", 2, 3 ); \endcode + /// + /// \par Output + /// str = string String( const char* c, int prefix_cut_off = 0, int sufix_cut_off = 0 ); @@ -49,7 +60,17 @@ class String static String getType(); ///// - /// \brief Copy constructor. Constructs a copy of the string \e str. + /// \brief Copy constructor. + /// + /// Constructs a copy of the string \e str. + /// + /// \par Example + /// \code + String str1( "Something" ); + String str2( str1 ); + /// \endcode + /// \par Output + /// str1 = Something \n str2 = Something String( const String& str ); /// \brief Converts anything to a string. @@ -72,103 +93,175 @@ class String /// Returns size of allocated storage for given string. int getAllocatedSize() const; - /// Reserves space for given number of characters (\e size). - /// Requests to allocate storage for given \e size (number of characters). + ///// + /// Reserves space for given \e size. + /// Requests to allocate storage for given \e size. + /// @param size Number of characters. void setSize( int size ); ///// - /// Sets string from given char pointer \e c. - /// @param prefix_cut_off determines the length of the prefix that is going to be omitted from the string \e c - /// @param sufix_cut_off determines the length of the sufix that is going to be omitted from the string \e c + /// \brief Sets string from given char pointer \e c. + /// + /// @param prefix_cut_off determines the length of the prefix that is + /// going to be omitted from the string \e c + /// @param sufix_cut_off determines the length of the sufix that is going + /// to be omitted from the string \e c void setString( const char* c, int prefix_cut_off = 0, int sufix_cut_off = 0 ); - /// Returns pointer to data. It returns the content of the given string. + ///// + /// \brief Returns pointer to data. + /// + /// It returns the content of the given string. The content can not be + /// changed by user. const char* getString() const; - /// Returns pointer to data. + /// \brief Returns pointer to data. + /// + /// It returns the content of the given string. The content can be changed + /// by user. char* getString(); - /// \brief Operator for accesing particular chars of the string. This function overloads operator[](). It returns a reference to the character at position \e i in given string. + ///// + /// \brief Operator for accesing particular chars of the string. + /// + /// This function overloads operator[](). It returns a reference to + /// the character at position \e i in given string. + /// The character can not be changed be user. const char& operator[]( int i ) const; - /// \brief Operator for accesing particular chars of the string. It returns the character at the position \e i in given string as a modifiable reference. + /// \brief Operator for accesing particular chars of the string. + /// + /// It returns the character at the position \e i in given string as + /// a modifiable reference. char& operator[]( int i ); ///// - /// \brief Operators for C strings. - /// This function overloads operator=(). It assigns \e str to this string, replacing its current contents. + // Operators for C strings. + + /// \brief This function overloads operator=(). + /// + /// It assigns C string \e str to this string, replacing its current contents. String& operator=( const char* str ); - /// This function overloads operator+=(). It appends the string \e str to this string. + /// \brief This function overloads operator+=(). + /// + /// It appends the C string \e str to this string. String& operator+=( const char* str ); - /// This function concatenates strings and returns a newly constructed string object. + /// \brief This function concatenates C strings \e str and returns a newly + /// constructed string object. String operator+( const char* str ) const; - /// This function overloads operator==(). + /// \brief This function overloads operator==(). bool operator==( const char* str ) const; - /// This function overloads operator!=(). + /// \brief This function overloads operator!=(). bool operator!=( const char* str ) const; ///// - /// \brief Operators for Strings. - /// This function assigns \e str to this string and returns a reference to this string. + // Operators for Strings. + + /// This function assigns \e str to this string and returns a reference to + /// this string. String& operator=( const String& str ); - /// This function appends the string \e str onto the end of this string and returns a reference to this string. + /// This function appends the string \e str onto the end of this string + /// and returns a reference to this string. String& operator+=( const String& str ); - /// This function concatenates strings and returns a newly constructed string object. + /// This function concatenates strings \e str and returns a newly + /// constructed string object. String operator+( const String& str ) const; - /// This function overloads operator==(). It returns \c true if this string is equal to \e str, otherwise returns \c false. + /// \brief This function overloads operator==(). + /// + /// It returns \c true if this string is equal to \e str, otherwise returns + /// \c false. bool operator==( const String& str ) const; - /// This function overloads operator!=(). It returns \c true if this string is not equal to \e str, otherwise returns \c false. + /// \brief This function overloads operator!=(). + /// + /// It returns \c true if this string is not equal to \e str, otherwise + /// returns \c false. bool operator!=( const String& str ) const; ///// - /// \brief Operators for single characters. - /// This function overloads operator=(). It assigns character /e str to this string. + // Operators for single characters. + + /// \brief This function overloads operator=(). + /// + /// It assigns character /e str to this string. String& operator=( char str ); - /// This function overloads operator+=(). It appends character /e str to this string. + /// \brief This function overloads operator+=(). + /// + /// It appends character /e str to this string. String& operator+=( char str ); // This function concatenates strings and returns a newly constructed string object. String operator+( char str ) const; // This function concatenates strings and returns a newly constructed string object. bool operator==( char str ) const; - /// This function overloads operator!=(). + /// \brief This function overloads operator!=(). bool operator!=( char str ) const; - /// \brief Cast to bool operator. Converts string to boolean expression (true or false). + /// \brief Cast to bool operator. + /// + /// This function overloads operator bool(). It converts string to boolean + /// expression (true or false). operator bool() const; /// \brief Cast to bool with negation operator. + /// + /// This function overloads operator!(). It converts string to boolean + /// expression (false or true). bool operator!() const; ///// /// \brief Replaces portion of string. - ///It replaces section \e pattern from this string with new piece of string \e replaceWith. - ///If parameter \e count is defined, the function makes replacement several times, every time when it finds the same pattern in this string. + /// + /// Replaces section \e pattern from this string with new piece of string \e replaceWith. + /// If parameter \e count is defined, the function makes replacement several times, + /// every time when it finds the same pattern in this string. + /// @param pattern Section of given string that will be replaced. + /// @param replaceWith New piece of string that will be used to replace \e pattern. + /// @param count A whole number that specifies how many replacements should be done. String replace( const String& pattern, const String& replaceWith, int count = 0 ) const; - /// \brief Trims/strips given string. It removes all spaces from string except for single spaces between words. + ///// + /// \brief Trims/strips given string. + /// + /// Removes all spaces from given string except for single spaces between words. String strip( char strip = ' ' ) const; /// \brief Splits string into list of strings with respect to given \e separator. - /// It splits the string into list of substrings wherever \e separator occurs, and returs list of those strings. - /// When \e separator does not appear anywhere in the given string, this function returns a single-element list containing given sting. - /// @param separator Character, which separates substrings in given string. Empty character can not be used. + /// + /// Splits the string into list of substrings wherever \e separator occurs, + /// and returs list of those strings. When \e separator does not appear + /// anywhere in the given string, this function returns a single-element list + /// containing given sting. + /// @param list Name of list. + /// @param separator Character, which separates substrings in given string. + /// Empty character can not be used. int split( Containers::List< String >& list, const char separator = ' ' ) const; - /// Writes to a binary file and returns boolean expression based on the success in writing into the file. + ///// + /// \brief Function for saving file. + /// + /// Writes to a binary file and returns boolean expression based on the + /// success in writing into the file. bool save( File& file ) const; - /// Reads from binary file and returns boolean expression based on the success in reading the file. + ///// + /// \brief Function for loading from file. + /// + /// Reads from binary file and returns boolean expression based on the + /// success in reading the file. bool load( File& file ); - /// !!! Mozem dat prec??? // Broadcast to other nodes in MPI cluster // void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); - /// Reads one line from given stream. + + ///// + /// \brief Function for getting a line from stream. + /// + /// Reads one line from given stream and returns either the line or boolean + /// expression based on the success in reading the line. bool getLine( std::istream& stream ); ///toto neviem co @@ -178,7 +271,7 @@ class String /// Pointer to char ended with zero ...Preco? char* string; - /// Length of the allocated piece of memory. + /// Length of allocated piece of memory. int length; }; -- GitLab From 81b720c776d770112dcc76e3b93f41990e7fa180 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Thu, 25 Oct 2018 16:07:37 +0200 Subject: [PATCH 065/111] Added first examples into String. --- src/TNL/String.h | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/TNL/String.h b/src/TNL/String.h index 056afd3fa..23ee67d53 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -26,13 +26,20 @@ template< typename T > String convertToString( const T& value ); ///// -// \brief Class for managing strings. +/// \brief Class for managing strings. +/// +/// \par Example +/// \include StringExample.cpp +/// \par Output +/// \include StringOutput.cpp class String { public: ///// - /// \brief Basic constructor. Constructs an empty string object, with the length of zero characters. + /// \brief Basic constructor. + /// + /// Constructs an empty string object with the length of zero characters. String(); ///// @@ -46,12 +53,6 @@ class String /// to be omitted from the string \e c. /// @param sufix_cut_off Determines the length of the sufix that is going /// to be omitted from the string \e c. - /// - /// \par Example - /// \code String str( "xxstringxxx", 2, 3 ); \endcode - /// - /// \par Output - /// str = string String( const char* c, int prefix_cut_off = 0, int sufix_cut_off = 0 ); @@ -63,17 +64,12 @@ class String /// \brief Copy constructor. /// /// Constructs a copy of the string \e str. - /// - /// \par Example - /// \code - String str1( "Something" ); - String str2( str1 ); - /// \endcode - /// \par Output - /// str1 = Something \n str2 = Something String( const String& str ); /// \brief Converts anything to a string. + /// + /// This function converts any type of value into type string. + /// @param value Word of any type (e.g. int, bool, double,...). template< typename T > explicit String( T value ) @@ -96,6 +92,7 @@ class String ///// /// Reserves space for given \e size. /// Requests to allocate storage for given \e size. + /// It allocates one more byte for the terminating 0. /// @param size Number of characters. void setSize( int size ); @@ -253,6 +250,8 @@ class String /// success in reading the file. bool load( File& file ); + + // !!! Mozem dat prec??? // Broadcast to other nodes in MPI cluster // void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); @@ -274,7 +273,7 @@ class String /// Length of allocated piece of memory. int length; -}; +}; // class String /// Returns concatenation of \e string1 and \e string2. String operator+( char string1, const String& string2 ); -- GitLab From c482eff23784d6f056ed7b9a70598272b1729681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Oberhuber?= Date: Sat, 27 Oct 2018 21:17:32 +0200 Subject: [PATCH 066/111] Doxygen omits directories without documentation. --- Doxyfile | 18 +++++++++++++++++- generate-doc | 3 ++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 649e477a4..2e7eec18c 100644 --- a/Doxyfile +++ b/Doxyfile @@ -889,7 +889,23 @@ EXCLUDE_SYMLINKS = NO # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS = */Communicators/* \ + */Config/* \ + */Containers/* \ + */Debugging/* \ + */Devices/* \ + */DistributedContainers/* \ + */Exceptions/* \ + */Experimental/* \ + */Functions/* \ + */Images/* \ + */Matrices/* \ + */Meshes/* \ + */Operators/* \ + */Pointers/* \ + */Problems/* \ + */Solvers/* + # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the diff --git a/generate-doc b/generate-doc index 6007851f4..9a2ad0ab9 100755 --- a/generate-doc +++ b/generate-doc @@ -15,6 +15,7 @@ done doxygen if [[ "$INSTALL" == "yes" ]]; then - cp -r Documentation/* ${PREFIX}/share/doc + mkdir -p ${PREFIX}/share/doc/tnl + cp -r Documentation/* ${PREFIX}/share/doc/tnl fi -- GitLab From d36432a82b6bf2a1e8441c857fefd33ccbd702a0 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 29 Oct 2018 13:57:58 +0100 Subject: [PATCH 067/111] String documentation. --- src/Examples/StringExample.cpp | 112 +++++++++++++++++++++++++++++++++ src/Examples/StringExample.out | 40 ++++++++++++ src/TNL/String.h | 4 +- 3 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 src/Examples/StringExample.cpp create mode 100644 src/Examples/StringExample.out diff --git a/src/Examples/StringExample.cpp b/src/Examples/StringExample.cpp new file mode 100644 index 000000000..1297f521f --- /dev/null +++ b/src/Examples/StringExample.cpp @@ -0,0 +1,112 @@ +#include + +using namespace TNL + +int main() +{ + // constructors + String str1; + String str2( "xxstringxxx", 2, 3 ); + String str3( str2 ); // copy constructor + String str4( 28.4 ); // converts to string + + cout << "str1:" << str1 << endl; + cout << "str2:" << str2 << endl; + cout << "str3:" << str3 << endl; + cout << "str4:" << str4 << endl; + + // functions + int size = str3.getSize(); + cout << "size of string:" << size << "bytes" << endl; + + int alloc_size = str3.getAllocatedSize(); + cout << "alloc_size:" << alloc_size << endl; + + int memory = str1.setSize( 256 ); + cout << "memory:" << memory << endl; + + String str + setter = str.setString( "Something new" ); + cout << "setter:" << setter << endl; + + int getter = str4.getString(); + cout << "getter:" << getter << endl; + + String word( computer ) ; + third_letter = word[2]; + cout << "third_letter:" << third_letter << endl; + + // Operators for C Strings + String a( "hello" ); + a = "bye"; + cout << "a:" << a << endl; + + String b( "see" ); + b += " you"; + cout << "b:" << b << endl; + + String c; + c = b + " soon"; + cout << "c:" << c << endl; + + String name( "Jack" ); + if ( name == "Jack" ) cout << "Names are the same." << endl; + + String surname( "Sparrow" ); + if ( surname != "Jones" ) cout << "Surnames are different." << endl; + + // Operators for Strings + String d1( "Cheese" ); + d = d1; + cout << "d:" << d << endl; + + String e( "Mac&" ); + e += d; + cout << "e:" << e << endl; + + String f; + String f1("Tim likes "); + f = f1 + e; + cout << "f:" << f << endl; + + String num1( "one" ); + String num2( "Anyone", 3); + if ( num1 == num2 ) cout << "Numbers are the same." << endl; + + String eq1( "a + b" ); + String eq2( "a" ); + if ( eq1 != eq2 ) cout << "Equations are different." << endl; + + // Operators for single characters + String g; + g = 'y'; + cout << "g:" << g << endl; + + String h( "x" ); + h += g; + cout << "h:" << h << endl; + + String i; + i = 'a' + 'b'; + cout << "i:" << i << endl; + + String letter1( "u" ); + if ( letter1 == "u" ) cout << "Letters are the same." << endl; + + String letter2( "v" ); + if ( letter2 != "w" ) cout << "Letters are different." << endl; + + //Cast to bool operators + String full( "string" ); + if ( full ) cout << "String is not empty." << endl; + + String empty; + if ( !empty ) cout << "String is empty." << endl; + + //replace + String phrase( "Hakuna matata" ); + new_phrase = phrase.replace( "a", "u", 2 ); + cout << "new_phrase:" << new_phrase << endl; + + +} diff --git a/src/Examples/StringExample.out b/src/Examples/StringExample.out new file mode 100644 index 000000000..4bc752b22 --- /dev/null +++ b/src/Examples/StringExample.out @@ -0,0 +1,40 @@ +//constructors +str1: +str2: string +str3: string +str4: 28.4 //string type + +//functions +size of string: 6 bytes +alloc_size: 256 +memory: 512 +setter: Something new +getter: 28.4 +third_letter: m + +// Operators for C Strings +a: bye +b: see you +c: see you soon +Names are the same. +Surnames are different. + +// Operators for Strings +d: Cheese +e: Mac&Cheese +f: Tim likes Mac&Cheese +Numbers are the same. +Equations are different. +// Operators for single characters +g: y +h: xy +i: ab +Letters are the same. +Letters are different. + +//Cast to bool operators +String is not empty. +String is empty. + +//replace +new_phrase: Hukunu matata diff --git a/src/TNL/String.h b/src/TNL/String.h index 23ee67d53..52d77bdcd 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -91,7 +91,7 @@ class String ///// /// Reserves space for given \e size. - /// Requests to allocate storage for given \e size. + /// Requests to allocate storage space of given \e size to avoid memory reallocation. /// It allocates one more byte for the terminating 0. /// @param size Number of characters. void setSize( int size ); @@ -251,7 +251,7 @@ class String bool load( File& file ); - // !!! Mozem dat prec??? + // !!! Mozem dat prec??? // Broadcast to other nodes in MPI cluster // void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); -- GitLab From 7a74d71a951e5fbe25d8609b2855ebc352d51a69 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 5 Nov 2018 16:56:24 +0100 Subject: [PATCH 068/111] More StringExamples and added FileNameTest --- src/Examples/StringExample.cpp | 48 ++++++++++++++++++++------- src/Examples/StringExample.out | 16 +++++++-- src/TNL/String.h | 2 +- src/UnitTests/FileNameTest.cpp | 59 ++++++++++++++++++++++++++++------ src/UnitTests/StringTest.cpp | 2 ++ 5 files changed, 104 insertions(+), 23 deletions(-) diff --git a/src/Examples/StringExample.cpp b/src/Examples/StringExample.cpp index 1297f521f..f33da1392 100644 --- a/src/Examples/StringExample.cpp +++ b/src/Examples/StringExample.cpp @@ -81,32 +81,58 @@ int main() String g; g = 'y'; cout << "g:" << g << endl; - + String h( "x" ); h += g; cout << "h:" << h << endl; - + String i; i = 'a' + 'b'; cout << "i:" << i << endl; - + String letter1( "u" ); if ( letter1 == "u" ) cout << "Letters are the same." << endl; - + String letter2( "v" ); if ( letter2 != "w" ) cout << "Letters are different." << endl; - - //Cast to bool operators + + // Cast to bool operators String full( "string" ); if ( full ) cout << "String is not empty." << endl; - + String empty; if ( !empty ) cout << "String is empty." << endl; - - //replace + + // replace String phrase( "Hakuna matata" ); new_phrase = phrase.replace( "a", "u", 2 ); cout << "new_phrase:" << new_phrase << endl; - - + + // strip + String names(" Josh Martin John Marley Charles "); + better_names = names.strip(); + cout << "better_names:" << better_names << endl; + + // split + String dates("3/4/2005;8/7/2011;11/12/2019"); + list_dates = dates.split( list, ';' ); + cout << "list_dates:" << list_dates << endl; + + // save + String("Header").save(my-file.tnl); // saves "Header" into file my-file.tnl + + // load + String strg; + strg.load(my-file.tnl); + cout << "strg:" << strg << endl; + + // get line + std::stringstream text; + text << "Hello!" << std::endl; + text << "What's up?" << std::endl; + + String str; + str.getLine( text ); + cout << "str:" << str << endl; + } diff --git a/src/Examples/StringExample.out b/src/Examples/StringExample.out index 4bc752b22..87170b8a9 100644 --- a/src/Examples/StringExample.out +++ b/src/Examples/StringExample.out @@ -32,9 +32,21 @@ i: ab Letters are the same. Letters are different. -//Cast to bool operators +// Cast to bool operators String is not empty. String is empty. -//replace +// replace new_phrase: Hukunu matata + +// strip +list_dates: 3/4/2005 8/7/2011 11/12/2019 + +// save +true + +// load +strg: Header + +// get line +str: Hello! \ No newline at end of file diff --git a/src/TNL/String.h b/src/TNL/String.h index 52d77bdcd..6b77d12f4 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -31,7 +31,7 @@ String convertToString( const T& value ); /// \par Example /// \include StringExample.cpp /// \par Output -/// \include StringOutput.cpp +/// \include StringExample.out class String { public: diff --git a/src/UnitTests/FileNameTest.cpp b/src/UnitTests/FileNameTest.cpp index 3f71be146..38192af05 100644 --- a/src/UnitTests/FileNameTest.cpp +++ b/src/UnitTests/FileNameTest.cpp @@ -15,22 +15,63 @@ #endif #include +#include using namespace TNL; #ifdef HAVE_GTEST TEST( FileNameTest, Constructor ) { - /*String str1( "string1" ); - String str2( "xxxstring2", 3 ); - String str3( "string3xxx", 0, 3 ); - String str4( "xxxstring4xxx", 3, 3 ); - - EXPECT_EQ( strcmp( str1.getString(), "string1" ), 0 ); - EXPECT_EQ( strcmp( str2.getString(), "string2" ), 0 ); - EXPECT_EQ( strcmp( str3.getString(), "string3" ), 0 ); - EXPECT_EQ( strcmp( str4.getString(), "string4" ), 0 );*/ + FileName fname; + + EXPECT_EQ( strcmp( fname.getFileName(), "00000." ), 0 ); +} + +TEST( FileNameTest, Base ) +{ + FileName fname; + fname.setFileNameBase("name"); + + EXPECT_EQ( strcmp( fname.getFileName(), "name00000." ), 0 ); +} + +/*TEST( FileNameTest, Extension ) +{ + FileName fname; + fname.setExtension("tnl"); + + EXPECT_EQ( strcmp( fname.getFileName(), "00000.tnl" ), 0 ); +}*/ + +/*TEST( FileNameTest, Index ) +{ + FileName fname1; + FileName fname2; + fname1.setIndex(1); + fname2.setIndex(50); + + EXPECT_EQ( strcmp( fname1.getFileName(), "00001." ), 0 ); + EXPECT_EQ( strcmp( fname2.getFileName(), "00050." ), 0 ); +}*/ + +/*TEST( FileNameTest, DigitsCount ) +{ + FileName fname; + fname.setDigitsCount(4); + + EXPECT_EQ( strcmp( fname.getFileName(), "0000." ), 0 ); } + +TEST( FileNameTest, AllTogether ) +{ + FileName fname; + fname.setFileNameBase("name"); + fname.setExtension("tnl"); + fname.setIndex(8); + fname.setDigitsCount(3); + + EXPECT_EQ( strcmp( fname.getFileName(), "name008.tnl" ), 0 ); +}*/ #endif diff --git a/src/UnitTests/StringTest.cpp b/src/UnitTests/StringTest.cpp index 9b85bd728..041c09b90 100644 --- a/src/UnitTests/StringTest.cpp +++ b/src/UnitTests/StringTest.cpp @@ -8,6 +8,8 @@ /* See Copyright Notice in tnl/Copyright */ +// Implemented by Nina Dzugasova + #ifdef HAVE_GTEST #include #endif -- GitLab From d099d5b70c51eeacb1ab53fd5d6d0b5cf53540e0 Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber Date: Tue, 6 Nov 2018 10:20:48 +0100 Subject: [PATCH 069/111] Fixed FileNameTest compilation. --- src/UnitTests/FileNameTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/UnitTests/FileNameTest.cpp b/src/UnitTests/FileNameTest.cpp index 38192af05..134a5f56a 100644 --- a/src/UnitTests/FileNameTest.cpp +++ b/src/UnitTests/FileNameTest.cpp @@ -24,7 +24,7 @@ TEST( FileNameTest, Constructor ) { FileName fname; - EXPECT_EQ( strcmp( fname.getFileName(), "00000." ), 0 ); + EXPECT_EQ( fname.getFileName(), "00000." ); } TEST( FileNameTest, Base ) @@ -32,7 +32,7 @@ TEST( FileNameTest, Base ) FileName fname; fname.setFileNameBase("name"); - EXPECT_EQ( strcmp( fname.getFileName(), "name00000." ), 0 ); + EXPECT_EQ( fname.getFileName(), "name00000." ); } /*TEST( FileNameTest, Extension ) -- GitLab From 4b4c6d20853b7b46cb52aeb7e6fe7fe801d9e7a5 Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber Date: Tue, 6 Nov 2018 10:21:04 +0100 Subject: [PATCH 070/111] Added compilation of StringExample. --- src/Examples/CMakeLists.txt | 4 ++++ src/Examples/StringExample.cpp | 17 ++++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/Examples/CMakeLists.txt b/src/Examples/CMakeLists.txt index 8fcc4a5de..305020587 100644 --- a/src/Examples/CMakeLists.txt +++ b/src/Examples/CMakeLists.txt @@ -17,3 +17,7 @@ add_subdirectory( flow-vl ) #add_subdirectory( hamilton-jacobi-parallel-map ) #add_subdirectory( fast-sweeping-map ) #add_subdirectory( narrow-band ) + + +ADD_EXECUTABLE( StringExample StringExample.cpp ) +target_link_libraries( StringExample tnl ) \ No newline at end of file diff --git a/src/Examples/StringExample.cpp b/src/Examples/StringExample.cpp index f33da1392..d6c45dee8 100644 --- a/src/Examples/StringExample.cpp +++ b/src/Examples/StringExample.cpp @@ -1,8 +1,10 @@ #include +#include -using namespace TNL +using namespace TNL; +using namespace std; -int main() +int main( int argc, char* argv[] ) { // constructors String str1; @@ -16,23 +18,24 @@ int main() cout << "str4:" << str4 << endl; // functions - int size = str3.getSize(); + /*int size = str3.getSize(); cout << "size of string:" << size << "bytes" << endl; int alloc_size = str3.getAllocatedSize(); cout << "alloc_size:" << alloc_size << endl; - int memory = str1.setSize( 256 ); - cout << "memory:" << memory << endl; + str1.setSize( 256 ); + size = str3.getSize(); + cout << "size of string:" << size << "bytes" << endl;*/ String str setter = str.setString( "Something new" ); cout << "setter:" << setter << endl; - int getter = str4.getString(); + const char* getter = str4.getString(); cout << "getter:" << getter << endl; - String word( computer ) ; + String word( "computer" ) ; third_letter = word[2]; cout << "third_letter:" << third_letter << endl; -- GitLab From e3f6c57ce36fab5e6ab51e305ccdf58c0ac5e495 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Tue, 6 Nov 2018 15:04:20 +0100 Subject: [PATCH 071/111] Added documentation for FileName. More FileNameTests. --- src/TNL/FileName.h | 31 +++++++++++++++++++++++++++---- src/TNL/String.h | 29 +++++++++++++++++++++++------ src/UnitTests/FileNameTest.cpp | 22 +++++++++++----------- 3 files changed, 61 insertions(+), 21 deletions(-) diff --git a/src/TNL/FileName.h b/src/TNL/FileName.h index ddf7c78d3..adb9ce88d 100644 --- a/src/TNL/FileName.h +++ b/src/TNL/FileName.h @@ -21,7 +21,10 @@ void removeFileExtension( String& file_name ); class FileName { public: - + + /// \brief Basic constructor. + /// + /// Constructs an empty filename object. FileName(); FileName( const String& fileNameBase ); @@ -29,12 +32,28 @@ class FileName FileName( const String& fileNameBase, const String& extension ); + + /// \brief Sets the base name of given file. + /// + /// Sets \e fileNameBase as the base name of given file. + /// @param fileNameBase String that specifies new name of file. void setFileNameBase( const String& fileNameBase ); - + + /// \brief Sets the extension of given file. + /// + /// Sets \e extension as suffix of a file name. + /// @param extension String that specifies extension of file (without dot). Suffix of a file name. E.g. doc, xls, tnl. void setExtension( const String& extension ); - + + // \brief Sets index for given file. + /// + /// Sets \e index after the base name of given file. + /// @param index Integer - number of maximum 5(default) digits. (Number of digits can be changed with \c setDigitsCount). void setIndex( const int index ); - + + // \brief Sets number of digits for index of given file. + /// + /// @param digitsCount Integer - number of digits. void setDigitsCount( const int digitsCount ); void setDistributedSystemNodeId( int nodeId ); @@ -42,6 +61,10 @@ class FileName template< typename Coordinates > void setDistributedSystemNodeId( const Coordinates& nodeId ); + /// Creates appropriate name for given file. + /// + /// Creates particular file name using \e fileNameBase, \e digitsCount, + /// \e index and \e extension. String getFileName(); protected: diff --git a/src/TNL/String.h b/src/TNL/String.h index 6b77d12f4..b18e784a6 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -39,7 +39,7 @@ class String ///// /// \brief Basic constructor. /// - /// Constructs an empty string object with the length of zero characters. + /// Constructs an empty string object. String(); ///// @@ -83,17 +83,34 @@ class String /// Returns the number of characters in given string. Equivalent to \c getSize(). int getLength() const; - /// Returns the number of characters in given string. + + /// \brief Returns the number of characters in given string. + /// + /// \par Example + /// \include StringExampleGetSize.cpp + /// \par Output + /// \include StringExampleGetSize.out int getSize() const; - /// Returns size of allocated storage for given string. + /// Returns size of allocated storage for given string. + /// + /// \par Example + /// \include StringExampleGetAllocatedSize.cpp + /// \par Output + /// \include StringExampleGetAllocatedSize.out int getAllocatedSize() const; ///// - /// Reserves space for given \e size. + /// \brief Reserves space for given \e size. + /// /// Requests to allocate storage space of given \e size to avoid memory reallocation. /// It allocates one more byte for the terminating 0. /// @param size Number of characters. + /// + /// \par Example + /// \include StringExampleSetSize.cpp + /// \par Output + /// \include StringExampleSetSize.out void setSize( int size ); ///// @@ -181,11 +198,11 @@ class String /// \brief This function overloads operator=(). /// - /// It assigns character /e str to this string. + /// It assigns character \e str to this string. String& operator=( char str ); /// \brief This function overloads operator+=(). /// - /// It appends character /e str to this string. + /// It appends character \e str to this string. String& operator+=( char str ); // This function concatenates strings and returns a newly constructed string object. String operator+( char str ) const; diff --git a/src/UnitTests/FileNameTest.cpp b/src/UnitTests/FileNameTest.cpp index 134a5f56a..8819b609c 100644 --- a/src/UnitTests/FileNameTest.cpp +++ b/src/UnitTests/FileNameTest.cpp @@ -35,31 +35,31 @@ TEST( FileNameTest, Base ) EXPECT_EQ( fname.getFileName(), "name00000." ); } -/*TEST( FileNameTest, Extension ) +TEST( FileNameTest, Extension ) { FileName fname; fname.setExtension("tnl"); - EXPECT_EQ( strcmp( fname.getFileName(), "00000.tnl" ), 0 ); -}*/ + EXPECT_EQ( fname.getFileName(), "00000.tnl" ); +} -/*TEST( FileNameTest, Index ) +TEST( FileNameTest, Index ) { FileName fname1; FileName fname2; fname1.setIndex(1); fname2.setIndex(50); - EXPECT_EQ( strcmp( fname1.getFileName(), "00001." ), 0 ); - EXPECT_EQ( strcmp( fname2.getFileName(), "00050." ), 0 ); -}*/ + EXPECT_EQ( fname1.getFileName(), "00001." ); + EXPECT_EQ( fname2.getFileName(), "00050." ); +} -/*TEST( FileNameTest, DigitsCount ) +TEST( FileNameTest, DigitsCount ) { FileName fname; fname.setDigitsCount(4); - EXPECT_EQ( strcmp( fname.getFileName(), "0000." ), 0 ); + EXPECT_EQ( fname.getFileName(), "0000." ); } TEST( FileNameTest, AllTogether ) @@ -70,8 +70,8 @@ TEST( FileNameTest, AllTogether ) fname.setIndex(8); fname.setDigitsCount(3); - EXPECT_EQ( strcmp( fname.getFileName(), "name008.tnl" ), 0 ); -}*/ + EXPECT_EQ( fname.getFileName(), "name008.tnl" ); +} #endif -- GitLab From b570813cea78408e4b4c1578e99e186a3ce5d152 Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber Date: Tue, 6 Nov 2018 15:51:01 +0100 Subject: [PATCH 072/111] Fixed documentation in string. --- src/TNL/String.h | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/src/TNL/String.h b/src/TNL/String.h index b18e784a6..b503c4d28 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -45,7 +45,6 @@ class String ///// /// \brief Constructor with char pointer. /// - /// Copies the null-terminated character sequence (C-string) pointed by \e c. /// Constructs a string initialized with the 8-bit string \e c, excluding /// the given number of \e prefix_cut_off and \e sufix_cut_off characters. /// @@ -69,6 +68,7 @@ class String /// \brief Converts anything to a string. /// /// This function converts any type of value into type string. + /// @tparam T is a type of a value to be converted /// @param value Word of any type (e.g. int, bool, double,...). template< typename T > explicit @@ -127,25 +127,23 @@ class String ///// /// \brief Returns pointer to data. /// - /// It returns the content of the given string. The content can not be - /// changed by user. + /// It returns the content of the given string as a constant pointer to char. const char* getString() const; /// \brief Returns pointer to data. /// - /// It returns the content of the given string. The content can be changed - /// by user. + /// It returns the content of the given string as a non-constant pointer to char. char* getString(); ///// - /// \brief Operator for accesing particular chars of the string. + /// \brief Operator for accessing particular chars of the string. /// /// This function overloads operator[](). It returns a reference to /// the character at position \e i in given string. /// The character can not be changed be user. const char& operator[]( int i ) const; - /// \brief Operator for accesing particular chars of the string. + /// \brief Operator for accessing particular chars of the string. /// /// It returns the character at the position \e i in given string as /// a modifiable reference. @@ -256,23 +254,17 @@ class String ///// /// \brief Function for saving file. /// - /// Writes to a binary file and returns boolean expression based on the + /// Writes the string to a binary file and returns boolean expression based on the /// success in writing into the file. bool save( File& file ) const; ///// /// \brief Function for loading from file. /// - /// Reads from binary file and returns boolean expression based on the + /// Reads a string from binary file and returns boolean expression based on the /// success in reading the file. bool load( File& file ); - - // !!! Mozem dat prec??? - // Broadcast to other nodes in MPI cluster - // void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); - - ///// /// \brief Function for getting a line from stream. /// @@ -280,11 +272,11 @@ class String /// expression based on the success in reading the line. bool getLine( std::istream& stream ); - ///toto neviem co friend std::ostream& operator<<( std::ostream& stream, const String& str ); protected: - /// Pointer to char ended with zero ...Preco? + + /// Pointer to char ended with zero byte char* string; /// Length of allocated piece of memory. @@ -298,7 +290,7 @@ String operator+( char string1, const String& string2 ); /// Returns concatenation of \e string1 and \e string2. String operator+( const char* string1, const String& string2 ); -/// Toto neviem co +/// Performs the string output to a stream std::ostream& operator<<( std::ostream& stream, const String& str ); template< typename T > -- GitLab From c144d98526aa5d6506af152fe35114de0956b073 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Thu, 8 Nov 2018 13:12:39 +0100 Subject: [PATCH 073/111] Documentation of Timer. --- src/Examples/StringExample.out | 2 +- src/TNL/FileName.h | 14 ++++++----- src/TNL/Timer.h | 46 +++++++++++++++++++++++++++++++--- src/UnitTests/FileNameTest.cpp | 3 ++- 4 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/Examples/StringExample.out b/src/Examples/StringExample.out index 87170b8a9..61886792a 100644 --- a/src/Examples/StringExample.out +++ b/src/Examples/StringExample.out @@ -5,7 +5,7 @@ str3: string str4: 28.4 //string type //functions -size of string: 6 bytes +size of string: 8 bytes alloc_size: 256 memory: 512 setter: Something new diff --git a/src/TNL/FileName.h b/src/TNL/FileName.h index adb9ce88d..601ced042 100644 --- a/src/TNL/FileName.h +++ b/src/TNL/FileName.h @@ -40,18 +40,20 @@ class FileName void setFileNameBase( const String& fileNameBase ); /// \brief Sets the extension of given file. - /// + /// /// Sets \e extension as suffix of a file name. - /// @param extension String that specifies extension of file (without dot). Suffix of a file name. E.g. doc, xls, tnl. + /// @param extension String that specifies extension of file (without dot). + /// Suffix of a file name. E.g. doc, xls, tnl. void setExtension( const String& extension ); - // \brief Sets index for given file. + /// \brief Sets index for given file. /// /// Sets \e index after the base name of given file. - /// @param index Integer - number of maximum 5(default) digits. (Number of digits can be changed with \c setDigitsCount). + /// @param index Integer - number of maximum 5(default) digits. + /// (Number of digits can be changed with \c setDigitsCount). void setIndex( const int index ); - // \brief Sets number of digits for index of given file. + /// \brief Sets number of digits for index of given file. /// /// @param digitsCount Integer - number of digits. void setDigitsCount( const int digitsCount ); @@ -62,7 +64,7 @@ class FileName void setDistributedSystemNodeId( const Coordinates& nodeId ); /// Creates appropriate name for given file. - /// + /// /// Creates particular file name using \e fileNameBase, \e digitsCount, /// \e index and \e extension. String getFileName(); diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index f885bdd44..13567a438 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -15,32 +15,67 @@ namespace TNL { class Logger; +/// \brief Class for time measuring class Timer { public: - + + ///// + /// \brief Basic constructor. + /// + /// This function creates a new timer. Timer(); + ///// + /// \brief Resets timer. + /// + /// Resets all time and cycle measurements such as real time, CPU time and CPU cycles. + /// Sets all of them to zero. void reset(); + //// + /// \brief Stops timer. + /// + /// Stops all time and cycle measurements such as real time, CPU time and CPU cycles. void stop(); + ///// + /// \brief Starts timer. + /// + /// Starts all time and cycle measurements such as real time, CPU time and CPU cycles. void start(); + /// \brief Counts the real (clock) time starting after the function \c start() is called. double getRealTime() const; + ///// + /// \brief Measures the CPU time. + /// + /// CPU time is the time that measures how long it takes processor + /// to complete all computations. double getCPUTime() const; + /// Counts the number of CPU cycles (machine cycles). unsigned long long int getCPUCycles() const; - + + /// \brief Writes a record to the \e logger. + /// + /// \param logger + /// \param logLevel bool writeLog( Logger& logger, int logLevel = 0 ) const; protected: - + + /// Function for reading the real time from timer. double readRealTime() const; + /// \brief Function for reading the CPU time from timer. + /// + /// CPU time is the time that measures how long it takes processor + /// to complete all computations. double readCPUTime() const; + /// \brief Function for reading the number of CPU cycles (machine cycles). unsigned long long int readCPUCycles() const; @@ -48,7 +83,10 @@ class Timer initialCPUTime, totalCPUTime; unsigned long long int initialCPUCycles, totalCPUCycles; - + + /// \brief Saves information about state of the timer. + /// + /// Knows whether the timer is currently stopped or not. bool stopState; inline unsigned long long rdtsc() const diff --git a/src/UnitTests/FileNameTest.cpp b/src/UnitTests/FileNameTest.cpp index 8819b609c..5a69a1f28 100644 --- a/src/UnitTests/FileNameTest.cpp +++ b/src/UnitTests/FileNameTest.cpp @@ -15,7 +15,7 @@ #endif #include -#include +// #include using namespace TNL; @@ -71,6 +71,7 @@ TEST( FileNameTest, AllTogether ) fname.setDigitsCount(3); EXPECT_EQ( fname.getFileName(), "name008.tnl" ); + EXPECT_EQ( getFileExtension(fname.getFileName()), "tnl" ); } #endif -- GitLab From f7e026d82adcfa95655c3f8ec30cee33dabfd728 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Fri, 9 Nov 2018 15:12:37 +0100 Subject: [PATCH 074/111] Started documentation of File. --- src/TNL/File.h | 15 ++++++++++++--- src/TNL/Timer.h | 6 +++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/TNL/File.h b/src/TNL/File.h index 7a8a024db..8ccfe90b1 100644 --- a/src/TNL/File.h +++ b/src/TNL/File.h @@ -36,9 +36,8 @@ enum class IOMode */ const size_t FileGPUvsCPUTransferBufferSize = 5 * 2<<20; -/* - * This file is aimed mainly for the binary data. It supports transparent compression. - */ + +/// Class file is aimed mainly for the binary data. It supports transparent compression. class File { IOMode mode; @@ -55,10 +54,19 @@ class File public: + /// Basic constructor. File(); + /// Destructor. ~File(); + ///// + /// \brief Opens given file. + /// + /// Opens file with given \e fileName and returns true/false based on the success in opening the file. + /// \param fileName String which indicates name of the file user wants to open. + /// \param mode Indicates what user needs to do with opened file. + /// Modes to choose: IOMode::read or IOMode::write. bool open( const String& fileName, const IOMode mode ); @@ -92,6 +100,7 @@ class File template< typename Type, typename Device = Devices::Host > bool write( const Type* buffer ); + /// \brief Closes given file and returns true/false based on the success in closing the file. bool close(); protected: diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index 13567a438..a0bd36ae8 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -66,10 +66,10 @@ class Timer protected: - /// Function for reading the real time from timer. + /// Function for reading the real time. double readRealTime() const; - /// \brief Function for reading the CPU time from timer. + /// \brief Function for reading the CPU time. /// /// CPU time is the time that measures how long it takes processor /// to complete all computations. @@ -84,7 +84,7 @@ class Timer unsigned long long int initialCPUCycles, totalCPUCycles; - /// \brief Saves information about state of the timer. + /// \brief Saves information about state of the timer. /// /// Knows whether the timer is currently stopped or not. bool stopState; -- GitLab From d6edf05a51ecba86ca0ea2f3fece730e39c1f42e Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Tue, 13 Nov 2018 09:49:24 +0100 Subject: [PATCH 075/111] Added String examples. --- src/Examples/StringExampleGetAllocatedSize.cpp | 10 ++++++++++ src/Examples/StringExampleGetSize.cpp | 11 +++++++++++ src/Examples/StringExampleSetSize.cpp | 10 ++++++++++ 3 files changed, 31 insertions(+) create mode 100644 src/Examples/StringExampleGetAllocatedSize.cpp create mode 100644 src/Examples/StringExampleGetSize.cpp create mode 100644 src/Examples/StringExampleSetSize.cpp diff --git a/src/Examples/StringExampleGetAllocatedSize.cpp b/src/Examples/StringExampleGetAllocatedSize.cpp new file mode 100644 index 000000000..993ad3df4 --- /dev/null +++ b/src/Examples/StringExampleGetAllocatedSize.cpp @@ -0,0 +1,10 @@ +#include + +using namespace TNL + +int main() +{ + String str("my world") + int alloc_size = str.getAllocatedSize(); + cout << "alloc_size:" << alloc_size << endl; +} \ No newline at end of file diff --git a/src/Examples/StringExampleGetSize.cpp b/src/Examples/StringExampleGetSize.cpp new file mode 100644 index 000000000..b2c30f63a --- /dev/null +++ b/src/Examples/StringExampleGetSize.cpp @@ -0,0 +1,11 @@ +#include + +using namespace TNL + +int main() +{ + String str("my world") + int size = str.getSize(); + cout << "size of string:" << size << "bytes" << endl; +} + diff --git a/src/Examples/StringExampleSetSize.cpp b/src/Examples/StringExampleSetSize.cpp new file mode 100644 index 000000000..2e53f88b6 --- /dev/null +++ b/src/Examples/StringExampleSetSize.cpp @@ -0,0 +1,10 @@ +#include + +using namespace TNL + +int main() +{ + int memory + memory.setSize( 256 ); + cout << "memory:" << memory << endl; +} -- GitLab From 23ca0c68c1dec974db74e3a7b9f87b2e04b7eb20 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Tue, 13 Nov 2018 09:50:04 +0100 Subject: [PATCH 076/111] Added unit tests for Timer. --- src/UnitTests/TimerTest.cpp | 45 +++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/UnitTests/TimerTest.cpp diff --git a/src/UnitTests/TimerTest.cpp b/src/UnitTests/TimerTest.cpp new file mode 100644 index 000000000..16acbbd21 --- /dev/null +++ b/src/UnitTests/TimerTest.cpp @@ -0,0 +1,45 @@ +/*************************************************************************** + FileNameTest.cpp - description + ------------------- + begin : Oct 17, 2018 + copyright : (C) 2018 by Tomas Oberhuber + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// Implemented by Nina Dzugasova + +#ifdef HAVE_GTEST +#include +#endif + +#include + +using namespace TNL; + +#ifdef HAVE_GTEST +TEST( TimerTest, Constructor ) +{ + Timer time; + time.reset(); + EXPECT_EQ(time.getRealTime(),0); + time.start(); + time.stop(); + EXPECT_NE(time.getRealTime(),0); +} +#endif + + +#include "GtestMissingError.h" +int main( int argc, char* argv[] ) +{ +#ifdef HAVE_GTEST + ::testing::InitGoogleTest( &argc, argv ); + return RUN_ALL_TESTS(); +#else + throw GtestMissingError(); +#endif +} + + -- GitLab From bad9de0ceb55e36fb253b6f07330fbb7c6ecf1be Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Tue, 13 Nov 2018 09:51:11 +0100 Subject: [PATCH 077/111] Starting with documentation of File. --- src/TNL/File.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TNL/File.h b/src/TNL/File.h index 8ccfe90b1..8f8d13ee6 100644 --- a/src/TNL/File.h +++ b/src/TNL/File.h @@ -61,7 +61,7 @@ class File ~File(); ///// - /// \brief Opens given file. + /// \brief Opens given file. /// /// Opens file with given \e fileName and returns true/false based on the success in opening the file. /// \param fileName String which indicates name of the file user wants to open. -- GitLab From bcb3df9553ad6e9bd85d72cbe93b93f93c8862b1 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Tue, 13 Nov 2018 15:03:20 +0100 Subject: [PATCH 078/111] Better documentation of Timer. --- src/TNL/Timer.h | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index a0bd36ae8..ecbba35d4 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -23,7 +23,7 @@ class Timer ///// /// \brief Basic constructor. /// - /// This function creates a new timer. + /// This function creates a new timer and resets it. Timer(); ///// @@ -34,48 +34,60 @@ class Timer void reset(); //// - /// \brief Stops timer. + /// \brief Stops (pauses) the timer. /// - /// Stops all time and cycle measurements such as real time, CPU time and CPU cycles. + /// Pauses all time and cycle measurements such as real time, CPU time and + /// CPU cycles, but does not set them to zero. void stop(); ///// /// \brief Starts timer. /// - /// Starts all time and cycle measurements such as real time, CPU time and CPU cycles. + /// Starts all time and cycle measurements such as real time, CPU time and + /// CPU cycles. Function start() can be used also after using stop() function. + /// The timer then continues measuring the time without reseting. void start(); - /// \brief Counts the real (clock) time starting after the function \c start() is called. + /// \brief Returs the real (clock/timer) time. + /// + /// It returns the elapsed time between calling the start() and stop() functions. + /// Starts counting the real time after the function start() is called and + /// pauses when the function stop() is called. + /// If the timer have been started more then one time without resetting, + /// the real time is counted by adding all intervals (between start and stop + /// functions) together. + /// This function can be called while the timer is running, there is no + /// need to use stop() function first. double getRealTime() const; ///// - /// \brief Measures the CPU time. + /// \brief Returns the CPU time. /// /// CPU time is the time that measures how long it takes processor /// to complete all computations. double getCPUTime() const; - /// Counts the number of CPU cycles (machine cycles). + /// Returns the number of CPU cycles (machine cycles). unsigned long long int getCPUCycles() const; /// \brief Writes a record to the \e logger. /// /// \param logger - /// \param logLevel + /// \param logLevel A whole number from zero up, which indicates the indent. bool writeLog( Logger& logger, int logLevel = 0 ) const; protected: - /// Function for reading the real time. + /// Function for measuring the real time. double readRealTime() const; - /// \brief Function for reading the CPU time. + /// \brief Function for measuring the CPU time. /// /// CPU time is the time that measures how long it takes processor /// to complete all computations. double readCPUTime() const; - /// \brief Function for reading the number of CPU cycles (machine cycles). + /// \brief Function for counting the number of CPU cycles (machine cycles). unsigned long long int readCPUCycles() const; -- GitLab From f12bd95cb98026f55b072419e0aa54e0ead6f1a2 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Tue, 13 Nov 2018 15:37:06 +0100 Subject: [PATCH 079/111] Added documentation of File. --- src/TNL/File.h | 14 +++++++++++--- src/TNL/Timer.h | 6 +++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/TNL/File.h b/src/TNL/File.h index 8f8d13ee6..029246647 100644 --- a/src/TNL/File.h +++ b/src/TNL/File.h @@ -37,7 +37,7 @@ enum class IOMode const size_t FileGPUvsCPUTransferBufferSize = 5 * 2<<20; -/// Class file is aimed mainly for the binary data. It supports transparent compression. +/// Class file is aimed mainly for the binary data. class File { IOMode mode; @@ -66,21 +66,23 @@ class File /// Opens file with given \e fileName and returns true/false based on the success in opening the file. /// \param fileName String which indicates name of the file user wants to open. /// \param mode Indicates what user needs to do with opened file. - /// Modes to choose: IOMode::read or IOMode::write. + /// Modes to choose: IOMode::read or IOMode::write or IOMode::undefined. bool open( const String& fileName, const IOMode mode ); - + /// \brief Returns name of given file. const String& getFileName() const { return this->fileName; } + /// Returns read elements. long int getReadElements() const { return this->readElements; } + /// Returns written elements. long int getWrittenElements() const { return this->writtenElements; @@ -90,6 +92,7 @@ class File bool read( Type* buffer, const Index& elements ); + // Toto je treba?? template< typename Type, typename Device = Devices::Host > bool read( Type* buffer ); @@ -97,6 +100,7 @@ class File bool write( const Type* buffer, const Index elements ); + // Toto je treba? template< typename Type, typename Device = Devices::Host > bool write( const Type* buffer ); @@ -147,6 +151,10 @@ protected: const std::size_t& elements ); }; +/// Returns true if the file exists and false otherwise. +/// +/// Finds out if the file \e fileName exists. +/// \param fileName Name of the file that user wants to find in the PC. bool fileExists( const String& fileName ); } // namespace TNL diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index ecbba35d4..8bf31c192 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -100,7 +100,10 @@ class Timer /// /// Knows whether the timer is currently stopped or not. bool stopState; - + + /// \brief Time Stamp Counter returning number of CPU cycles since reset. + /// + /// Only for x86 compatibile CPUs. inline unsigned long long rdtsc() const { unsigned hi, lo; @@ -109,6 +112,7 @@ class Timer } }; +// !!! Odstranit ???!!! extern Timer defaultTimer; } // namespace TNL -- GitLab From 76cb6966d0c29034d25be10b5897fa33c3f3aa75 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Wed, 14 Nov 2018 12:02:28 +0100 Subject: [PATCH 080/111] Added documentation into file. --- src/TNL/File.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/TNL/File.h b/src/TNL/File.h index 029246647..8e0836b35 100644 --- a/src/TNL/File.h +++ b/src/TNL/File.h @@ -88,6 +88,11 @@ class File return this->writtenElements; } + /// \brief Function that gets elements from given file. + /// + /// Returns boolean value based on the succes in reading elements from given file. + /// \param buffer Pointer in memory. + /// \param elements Number of elements the user wants to get (read) from given file. template< typename Type, typename Device = Devices::Host, typename Index = int > bool read( Type* buffer, const Index& elements ); @@ -96,6 +101,11 @@ class File template< typename Type, typename Device = Devices::Host > bool read( Type* buffer ); + /// \brief Function that writes elements into given file. + /// + /// Returns boolean value based on the succes in writing elements into given file. + /// \param buffer Pointer in memory. + /// \param elements Number of elements the user wants to write into the given file. template< typename Type, typename Device = Devices::Host, typename Index = int > bool write( const Type* buffer, const Index elements ); -- GitLab From 432b7aeadb5cf71df80ed5237d4e30a918827174 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Wed, 14 Nov 2018 14:59:25 +0100 Subject: [PATCH 081/111] Added documentation to Logger. --- src/TNL/File.h | 4 ++-- src/TNL/Logger.h | 15 ++++++++++++++- src/TNL/Timer.h | 6 +++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/TNL/File.h b/src/TNL/File.h index 8e0836b35..b690d610c 100644 --- a/src/TNL/File.h +++ b/src/TNL/File.h @@ -88,7 +88,7 @@ class File return this->writtenElements; } - /// \brief Function that gets elements from given file. + /// \brief Method that can write particular data type from given file into GPU. (Function that gets particular elements from given file.) /// /// Returns boolean value based on the succes in reading elements from given file. /// \param buffer Pointer in memory. @@ -101,7 +101,7 @@ class File template< typename Type, typename Device = Devices::Host > bool read( Type* buffer ); - /// \brief Function that writes elements into given file. + /// \brief Method that can write particular data type from CPU into given file. (Function that writes particular elements into given file.) /// /// Returns boolean value based on the succes in writing elements into given file. /// \param buffer Pointer in memory. diff --git a/src/TNL/Logger.h b/src/TNL/Logger.h index 5b7fda238..c6e672d4f 100644 --- a/src/TNL/Logger.h +++ b/src/TNL/Logger.h @@ -19,16 +19,29 @@ class Logger { public: + /// \brief Basic constructor. + /// + /// \param _width Integer that defines the width of logger. + /// \param _stream Where to create the logger, e.g. cout or a certain file.s Logger( int _width, std::ostream& _stream ); + /// \brief Creates header in given logger. + /// + /// \param title String desribing the title/header. void writeHeader( const String& title ); + /// \brief Creates predefined separator - structure in the logger. void writeSeparator(); + /// \brief Inserts information about system parameters into logger. + /// + /// \param parameters bool writeSystemInformation( const Config::ParameterContainer& parameters ); - + /// \brief Inserts a line with current time into logger. + /// + /// \param label Description of the current time line. void writeCurrentTime( const char* label ); // TODO: add units diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index 8bf31c192..3d40bc485 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -53,7 +53,7 @@ class Timer /// It returns the elapsed time between calling the start() and stop() functions. /// Starts counting the real time after the function start() is called and /// pauses when the function stop() is called. - /// If the timer have been started more then one time without resetting, + /// If the timer have been started more then once without resetting, /// the real time is counted by adding all intervals (between start and stop /// functions) together. /// This function can be called while the timer is running, there is no @@ -70,7 +70,7 @@ class Timer /// Returns the number of CPU cycles (machine cycles). unsigned long long int getCPUCycles() const; - /// \brief Writes a record to the \e logger. + /// \brief Writes a record into the \e logger. /// /// \param logger /// \param logLevel A whole number from zero up, which indicates the indent. @@ -96,7 +96,7 @@ class Timer unsigned long long int initialCPUCycles, totalCPUCycles; - /// \brief Saves information about state of the timer. + /// \brief Saves information about the state of given timer. /// /// Knows whether the timer is currently stopped or not. bool stopState; -- GitLab From 7f6aced6efdf99e140fdac06a2c15f3db344150b Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Thu, 15 Nov 2018 14:14:03 +0100 Subject: [PATCH 082/111] Added documentation into Containers/List. --- src/TNL/Containers/List.h | 63 ++++++++++++++++++++++--------------- src/TNL/File.h | 4 +-- src/TNL/Logger.h | 5 ++- src/UnitTests/TimerTest.cpp | 8 +++-- 4 files changed, 50 insertions(+), 30 deletions(-) diff --git a/src/TNL/Containers/List.h b/src/TNL/Containers/List.h index c64a8a957..2f53ccd8c 100644 --- a/src/TNL/Containers/List.h +++ b/src/TNL/Containers/List.h @@ -43,27 +43,34 @@ template< class T > class List public: typedef T ValueType; - //! Basic constructor + /// \brief Basic constructor. + /// + /// Constructs an empty list. List(); - //! Copy constructor + /// \brief Copy constructor. + /// + /// Construct a copy of \e list. + /// @param list Name of another list. List( const List& list ); - //! Destructor + /// \brief Destructor. + /// + /// Destroys the list. References to the values in the list become invalid. ~List(); static String getType(); - //! If the list is empty return 'true' + /// Returns \e true if the list contains no items, otherwise returns \e false. bool isEmpty() const; - //! Return size of the list + /// Returns number of items in the list. int getSize() const; - //! Indexing operator + /// Indexing operator. T& operator[] ( const int& ind ); - //! Indexing operator for constant instances + /// Indexing operator for constant instances. const T& operator[] ( const int& ind ) const; const List& operator = ( const List& lst ); @@ -72,64 +79,70 @@ template< class T > class List bool operator != ( const List& lst ) const; - //! Append new data element + /// \brief Appends new data element. + /// + /// Inserts \e data at the end of the list. bool Append( const T& data ); - //! Prepend new data element + /// \brief Prepends new data element. + /// + /// Inserts \e data at the beginning of the list. bool Prepend( const T& data ); - //! Insert new data element at given position + /// \brief Inserts new data element at given position. + /// + /// Inserts \e data at index position \e ind in the list. bool Insert( const T& data, const int& ind ); - //! Append copy of another list + /// Appends copy of another list. bool AppendList( const List< T >& lst ); - //! Prepend copy of another list + /// Prepends copy of another list. bool PrependList( const List< T >& lst ); template< typename Array > void toArray( Array& array ); - //! Erase data element at given position + /// Erases data element at given position. void Erase( const int& ind ); - //! Erase data element with contained data at given position + /// Erases data element with contained data at given position. void DeepErase( const int& ind ); - //! Erase all data elements + /// Erases all data elements. void reset(); - //! Erase all data elements with contained data + /// Erases all data elements with contained data. void DeepEraseAll(); - //! Save the list in binary format + /// Saves the list in binary format. bool Save( File& file ) const; - //! Save the list in binary format using method save of type T + /// Saves the list in binary format using method save of type T. bool DeepSave( File& file ) const; - //! Load the list + /// Loads the list. bool Load( File& file ); - //! Load the list using method Load of the type T + /// Loads the list using method Load of the type T. bool DeepLoad( File& file ); protected: - //! Pointer to the first element + /// Pointer to the first element. ListDataElement< T >* first; - //! Pointer to the last element + /// Pointer to the last element. /*! We use pointer to last element while adding new element to keep order of elements */ ListDataElement< T >* last; - //! List size + /// List size. int size; - //! Iterator + /// Iterator. mutable ListDataElement< T >* iterator; - //! Iterator index + /// Iterator index. mutable int index; }; diff --git a/src/TNL/File.h b/src/TNL/File.h index b690d610c..c156113f0 100644 --- a/src/TNL/File.h +++ b/src/TNL/File.h @@ -76,13 +76,13 @@ class File return this->fileName; } - /// Returns read elements. + /// Returns number of read elements. long int getReadElements() const { return this->readElements; } - /// Returns written elements. + /// Returns number of written elements. long int getWrittenElements() const { return this->writtenElements; diff --git a/src/TNL/Logger.h b/src/TNL/Logger.h index c6e672d4f..87298f9e4 100644 --- a/src/TNL/Logger.h +++ b/src/TNL/Logger.h @@ -19,6 +19,7 @@ class Logger { public: + ///// /// \brief Basic constructor. /// /// \param _width Integer that defines the width of logger. @@ -26,6 +27,7 @@ class Logger Logger( int _width, std::ostream& _stream ); + ///// /// \brief Creates header in given logger. /// /// \param title String desribing the title/header. @@ -34,11 +36,12 @@ class Logger /// \brief Creates predefined separator - structure in the logger. void writeSeparator(); - /// \brief Inserts information about system parameters into logger. + /// \brief Inserts information about various system parameters into logger. /// /// \param parameters bool writeSystemInformation( const Config::ParameterContainer& parameters ); + ///// /// \brief Inserts a line with current time into logger. /// /// \param label Description of the current time line. diff --git a/src/UnitTests/TimerTest.cpp b/src/UnitTests/TimerTest.cpp index 16acbbd21..6c20c4abb 100644 --- a/src/UnitTests/TimerTest.cpp +++ b/src/UnitTests/TimerTest.cpp @@ -24,9 +24,13 @@ TEST( TimerTest, Constructor ) Timer time; time.reset(); EXPECT_EQ(time.getRealTime(),0); - time.start(); + /*time.start(); + EXPECT_FALSE(time.stopState); + time.stop(); - EXPECT_NE(time.getRealTime(),0); + EXPECT_TRUE(time.stopState); + + EXPECT_NE(time.getRealTime(),0);*/ } #endif -- GitLab From 38e93f30f584c5ee81fddc3483e3302f62917ae7 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 19 Nov 2018 15:44:10 +0100 Subject: [PATCH 083/111] Only small adjustments. --- src/TNL/Containers/List.h | 4 +++- src/TNL/File.h | 7 ++++++- src/TNL/Logger.h | 2 +- src/TNL/Timer.h | 16 ++++++++++++---- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/TNL/Containers/List.h b/src/TNL/Containers/List.h index 2f53ccd8c..3954b014e 100644 --- a/src/TNL/Containers/List.h +++ b/src/TNL/Containers/List.h @@ -112,7 +112,9 @@ template< class T > class List /// Erases all data elements. void reset(); - /// Erases all data elements with contained data. + /// \brief Erases all data elements with contained data. + /// + /// Frees dynamicaly allocated data inside the data elements void DeepEraseAll(); /// Saves the list in binary format. diff --git a/src/TNL/File.h b/src/TNL/File.h index c156113f0..c6f55ff76 100644 --- a/src/TNL/File.h +++ b/src/TNL/File.h @@ -38,6 +38,11 @@ const size_t FileGPUvsCPUTransferBufferSize = 5 * 2<<20; /// Class file is aimed mainly for the binary data. +/// +/// \par Example +/// \include FileExample.cpp +// \par Output +// \include FileExample.out class File { IOMode mode; @@ -91,7 +96,7 @@ class File /// \brief Method that can write particular data type from given file into GPU. (Function that gets particular elements from given file.) /// /// Returns boolean value based on the succes in reading elements from given file. - /// \param buffer Pointer in memory. + /// \param buffer Pointer in memory (where the read elements are stored?). /// \param elements Number of elements the user wants to get (read) from given file. template< typename Type, typename Device = Devices::Host, typename Index = int > bool read( Type* buffer, diff --git a/src/TNL/Logger.h b/src/TNL/Logger.h index 87298f9e4..10ecf800c 100644 --- a/src/TNL/Logger.h +++ b/src/TNL/Logger.h @@ -23,7 +23,7 @@ class Logger /// \brief Basic constructor. /// /// \param _width Integer that defines the width of logger. - /// \param _stream Where to create the logger, e.g. cout or a certain file.s + /// \param _stream Where to create the logger, e.g. cout or a certain files. Logger( int _width, std::ostream& _stream ); diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index 3d40bc485..1ccc27537 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -15,7 +15,12 @@ namespace TNL { class Logger; -/// \brief Class for time measuring +/// \brief Class for time measuring. +/// +/// \par Example +/// \include TimerExample.cpp +// \par Output +// \include TimerExample.out class Timer { public: @@ -48,7 +53,8 @@ class Timer /// The timer then continues measuring the time without reseting. void start(); - /// \brief Returs the real (clock/timer) time. + ///// + /// \brief Returs the elapsed time on given timer. /// /// It returns the elapsed time between calling the start() and stop() functions. /// Starts counting the real time after the function start() is called and @@ -61,7 +67,7 @@ class Timer double getRealTime() const; ///// - /// \brief Returns the CPU time. + /// \brief Returns the elapsed CPU time on given timer. /// /// CPU time is the time that measures how long it takes processor /// to complete all computations. @@ -78,7 +84,9 @@ class Timer protected: - /// Function for measuring the real time. + /// \brief Function for measuring the real time. + /// + /// Returns the current calendar time. double readRealTime() const; /// \brief Function for measuring the CPU time. -- GitLab From 7cf148ad375888ac2b9aa028599e4012e6bd460e Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Tue, 20 Nov 2018 10:23:45 +0100 Subject: [PATCH 084/111] Added examples for File and Timer. --- src/Examples/FileExample.cpp | 25 +++++++++++++++++++++++++ src/Examples/TimerExample.cpp | 15 +++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/Examples/FileExample.cpp create mode 100644 src/Examples/TimerExample.cpp diff --git a/src/Examples/FileExample.cpp b/src/Examples/FileExample.cpp new file mode 100644 index 000000000..e0e81ab91 --- /dev/null +++ b/src/Examples/FileExample.cpp @@ -0,0 +1,25 @@ +#include +#include +#include + +using namespace TNL; +using namespace std; + +int main() +{ + File file; + + file.open( String("new-file.tnl"), IOMode::write ); + String title("Header"); + file.write( title ); + file.close(); + + file.open( String("new-file.tnl"), IOMode::read ); + String title2; + file.read( title2, 4); + file.close(); + + if fileExists( "new-file.tnl" ) + std::remove( "new-file.tnl" ); +} + diff --git a/src/Examples/TimerExample.cpp b/src/Examples/TimerExample.cpp new file mode 100644 index 000000000..772c9907b --- /dev/null +++ b/src/Examples/TimerExample.cpp @@ -0,0 +1,15 @@ +#include +#include + +using namespace TNL; +using namespace std; + +int main() +{ + Timer time; + time.start(); + time.stop(); + time.getRealTime(); + time.reset(); +} + -- GitLab From 939f3dcbe46c8165ffeb2bf0f142122b5146feb0 Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber Date: Tue, 20 Nov 2018 13:18:55 +0100 Subject: [PATCH 085/111] Fixing documentation. --- src/Examples/CMakeLists.txt | 7 ++++++- src/TNL/File.h | 2 +- src/TNL/Logger.h | 27 +++++++++++++++------------ src/TNL/Logger_impl.h | 10 +++++----- src/TNL/Timer.h | 2 +- 5 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/Examples/CMakeLists.txt b/src/Examples/CMakeLists.txt index 305020587..b8e7c574a 100644 --- a/src/Examples/CMakeLists.txt +++ b/src/Examples/CMakeLists.txt @@ -18,6 +18,11 @@ add_subdirectory( flow-vl ) #add_subdirectory( fast-sweeping-map ) #add_subdirectory( narrow-band ) +ADD_EXECUTABLE( FileExample FileExample.cpp ) +target_link_libraries( FileExample tnl ) ADD_EXECUTABLE( StringExample StringExample.cpp ) -target_link_libraries( StringExample tnl ) \ No newline at end of file +target_link_libraries( StringExample tnl ) + +ADD_EXECUTABLE( TimerExample TimerExample.cpp ) +target_link_libraries( TimerExample tnl ) \ No newline at end of file diff --git a/src/TNL/File.h b/src/TNL/File.h index c6f55ff76..bb31cdcd2 100644 --- a/src/TNL/File.h +++ b/src/TNL/File.h @@ -37,7 +37,7 @@ enum class IOMode const size_t FileGPUvsCPUTransferBufferSize = 5 * 2<<20; -/// Class file is aimed mainly for the binary data. +///\brief Class file is aimed mainly for the binary data. /// /// \par Example /// \include FileExample.cpp diff --git a/src/TNL/Logger.h b/src/TNL/Logger.h index 10ecf800c..bddcfeeeb 100644 --- a/src/TNL/Logger.h +++ b/src/TNL/Logger.h @@ -15,6 +15,7 @@ namespace TNL { +/// Vytvari tabulku s logem vypoctu class Logger { public: @@ -22,41 +23,43 @@ class Logger ///// /// \brief Basic constructor. /// - /// \param _width Integer that defines the width of logger. - /// \param _stream Where to create the logger, e.g. cout or a certain files. + /// \param _width Integer that defines the width of the log. + /// \param _stream Defines output stream where the log will be printed out. Logger( int _width, std::ostream& _stream ); ///// - /// \brief Creates header in given logger. + /// \brief Creates header in given log. + /// + /// The header usually contains title of the program. /// - /// \param title String desribing the title/header. + /// \param title String containing the header title. void writeHeader( const String& title ); - /// \brief Creates predefined separator - structure in the logger. + /// \brief Creates separator for structuring the log. void writeSeparator(); - /// \brief Inserts information about various system parameters into logger. + /// \brief Inserts information about various system parameters into the log. /// - /// \param parameters + /// \param parameters is a container with configuration parameters bool writeSystemInformation( const Config::ParameterContainer& parameters ); ///// - /// \brief Inserts a line with current time into logger. + /// \brief Inserts a line with current time into the log. /// - /// \param label Description of the current time line. + /// \param label Label to be printed to the log together with the current time. void writeCurrentTime( const char* label ); // TODO: add units - template< typename T > + template< typename ParameterType > void writeParameter( const String& label, const String& parameterName, const Config::ParameterContainer& parameters, int parameterLevel = 0 ); - template< typename T > + template< typename ParameterType > void writeParameter( const String& label, - const T& value, + const ParameterType& value, int parameterLevel = 0 ); protected: diff --git a/src/TNL/Logger_impl.h b/src/TNL/Logger_impl.h index e50233266..08181070f 100644 --- a/src/TNL/Logger_impl.h +++ b/src/TNL/Logger_impl.h @@ -15,7 +15,7 @@ namespace TNL { -template< typename T > +template< typename ParameterType > void Logger::writeParameter( const String& label, const String& parameterName, const Config::ParameterContainer& parameters, @@ -26,16 +26,16 @@ void Logger::writeParameter( const String& label, for( i = 0; i < parameterLevel; i ++ ) stream << " "; std::stringstream str; - str << parameters.getParameter< T >( parameterName ); + str << parameters.getParameter< ParameterType >( parameterName ); stream << label << std::setw( width - label.getLength() - parameterLevel - 3 ) << str.str() << " |" << std::endl; } -template< typename T > +template< typename ParameterType > void Logger :: writeParameter( const String& label, - const T& value, - int parameterLevel ) + const ParameterType& value, + int parameterLevel ) { stream << "| "; int i; diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index 1ccc27537..f347c4510 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -54,7 +54,7 @@ class Timer void start(); ///// - /// \brief Returs the elapsed time on given timer. + /// \brief Returns the elapsed time on given timer. /// /// It returns the elapsed time between calling the start() and stop() functions. /// Starts counting the real time after the function start() is called and -- GitLab From 81a69d823ddd2a3540604d5a8c0348361bef5ce5 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Tue, 20 Nov 2018 15:52:03 +0100 Subject: [PATCH 086/111] Added adjustments in documentation of Timer and File. --- src/Examples/FileExample.cpp | 3 +-- src/Examples/TimerExample.cpp | 3 +++ src/TNL/File.h | 20 ++++++++++++++------ src/TNL/Timer.h | 14 +++++++------- 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/Examples/FileExample.cpp b/src/Examples/FileExample.cpp index e0e81ab91..f5f3912dd 100644 --- a/src/Examples/FileExample.cpp +++ b/src/Examples/FileExample.cpp @@ -19,7 +19,6 @@ int main() file.read( title2, 4); file.close(); - if fileExists( "new-file.tnl" ) - std::remove( "new-file.tnl" ); + cout << "title2:" << title2 < #include +#include using namespace TNL; using namespace std; int main() { + unsigned int microseconds = 0.5; Timer time; time.start(); + usleep(microseconds); time.stop(); time.getRealTime(); time.reset(); diff --git a/src/TNL/File.h b/src/TNL/File.h index bb31cdcd2..20fb1fe7b 100644 --- a/src/TNL/File.h +++ b/src/TNL/File.h @@ -37,7 +37,7 @@ enum class IOMode const size_t FileGPUvsCPUTransferBufferSize = 5 * 2<<20; -///\brief Class file is aimed mainly for the binary data. +///\brief Class file is aimed mainly for saving and loading binary data. /// /// \par Example /// \include FileExample.cpp @@ -59,10 +59,10 @@ class File public: - /// Basic constructor. + /// \brief Basic constructor. File(); - /// Destructor. + /// \brief Destructor. ~File(); ///// @@ -95,8 +95,12 @@ class File /// \brief Method that can write particular data type from given file into GPU. (Function that gets particular elements from given file.) /// - /// Returns boolean value based on the succes in reading elements from given file. - /// \param buffer Pointer in memory (where the read elements are stored?). + /// Returns \e true when the elements are successfully read from given file. Otherwise returns \e false. + /// + /// \tparam Type Type of data. + /// \tparam Device Place where data are stored after reading from file. For example Devices::Host or Devices::Cuda. + /// \tparam Index Type of index by which the elements are indexed. + /// \param buffer Pointer in memory where the elements are loaded and stored after reading. /// \param elements Number of elements the user wants to get (read) from given file. template< typename Type, typename Device = Devices::Host, typename Index = int > bool read( Type* buffer, @@ -109,7 +113,11 @@ class File /// \brief Method that can write particular data type from CPU into given file. (Function that writes particular elements into given file.) /// /// Returns boolean value based on the succes in writing elements into given file. - /// \param buffer Pointer in memory. + /// + /// \tparam Type Type of data. + /// \tparam Device Place from where data are loaded before writing into file. For example Devices::Host or Devices::Cuda. + /// \tparam Index Type of index by which the elements are indexed. + /// \param buffer Pointer in memory from where the elements are loaded before writing into file. /// \param elements Number of elements the user wants to write into the given file. template< typename Type, typename Device = Devices::Host, typename Index = int > bool write( const Type* buffer, diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index f347c4510..b90fabce7 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -49,21 +49,21 @@ class Timer /// \brief Starts timer. /// /// Starts all time and cycle measurements such as real time, CPU time and - /// CPU cycles. Function start() can be used also after using stop() function. + /// CPU cycles. Method start() can be used also after using stop() method. /// The timer then continues measuring the time without reseting. void start(); ///// /// \brief Returns the elapsed time on given timer. /// - /// It returns the elapsed time between calling the start() and stop() functions. - /// Starts counting the real time after the function start() is called and - /// pauses when the function stop() is called. + /// It returns the elapsed time between calling the start() and stop() methods. + /// Starts counting the real time after the method start() is called and + /// pauses when the method stop() is called. /// If the timer have been started more then once without resetting, /// the real time is counted by adding all intervals (between start and stop - /// functions) together. + /// methods) together. /// This function can be called while the timer is running, there is no - /// need to use stop() function first. + /// need to use stop() method first. double getRealTime() const; ///// @@ -86,7 +86,7 @@ class Timer /// \brief Function for measuring the real time. /// - /// Returns the current calendar time. + /// Returns number of seconds since Epoch, 1970-01-01 00:00:00 UTC. double readRealTime() const; /// \brief Function for measuring the CPU time. -- GitLab From 3e39df89f5d456d3a73537e8ac219eebdfd0e677 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Wed, 21 Nov 2018 12:15:43 +0100 Subject: [PATCH 087/111] Made changes in TimerExample. --- src/Examples/TimerExample.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Examples/TimerExample.cpp b/src/Examples/TimerExample.cpp index 4ca3e5827..5817198c0 100644 --- a/src/Examples/TimerExample.cpp +++ b/src/Examples/TimerExample.cpp @@ -12,7 +12,8 @@ int main() time.start(); usleep(microseconds); time.stop(); - time.getRealTime(); + cout << "before reset:" << time.getRealTime() << endl; time.reset(); + cout << "after reset:" << time.getRealTime() << endl; } -- GitLab From 5a334993107aca13166a6a4f23b5c7ba094db1ad Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Wed, 21 Nov 2018 12:50:32 +0100 Subject: [PATCH 088/111] Modified the Timer documentation. --- src/Examples/TimerExample.cpp | 1 + src/TNL/Timer.h | 23 +++++++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/Examples/TimerExample.cpp b/src/Examples/TimerExample.cpp index 5817198c0..49bafb25c 100644 --- a/src/Examples/TimerExample.cpp +++ b/src/Examples/TimerExample.cpp @@ -15,5 +15,6 @@ int main() cout << "before reset:" << time.getRealTime() << endl; time.reset(); cout << "after reset:" << time.getRealTime() << endl; + // writeLog example } diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index b90fabce7..05a6de3ed 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -17,6 +17,7 @@ class Logger; /// \brief Class for time measuring. /// +/// Counts the elapsed time in seconds between the start() and stop() methods. /// \par Example /// \include TimerExample.cpp // \par Output @@ -56,7 +57,7 @@ class Timer ///// /// \brief Returns the elapsed time on given timer. /// - /// It returns the elapsed time between calling the start() and stop() methods. + /// It returns the elapsed time (in seconds) between calling the start() and stop() methods. /// Starts counting the real time after the method start() is called and /// pauses when the method stop() is called. /// If the timer have been started more then once without resetting, @@ -69,17 +70,23 @@ class Timer ///// /// \brief Returns the elapsed CPU time on given timer. /// - /// CPU time is the time that measures how long it takes processor - /// to complete all computations. + /// The CPU time is measured in seconds. + /// CPU time is the amount of time for which a central processing unit (CPU) + /// was used for processing instructions of a computer program or operating system. + /// The CPU time is measured by adding the amount of CPU time between start() and stop() + /// methods together. double getCPUTime() const; - /// Returns the number of CPU cycles (machine cycles). + /// \brief Returns the number of CPU cycles (machine cycles). + /// + /// CPU cycles are counted by adding the number of CPU cycles between start() and stop() + /// methods together. unsigned long long int getCPUCycles() const; /// \brief Writes a record into the \e logger. /// /// \param logger - /// \param logLevel A whole number from zero up, which indicates the indent. + /// \param logLevel A non-negative integer recording the log record indent. bool writeLog( Logger& logger, int logLevel = 0 ) const; protected: @@ -91,8 +98,8 @@ class Timer /// \brief Function for measuring the CPU time. /// - /// CPU time is the time that measures how long it takes processor - /// to complete all computations. + /// CPU time is the amount of time for which a central processing unit (CPU) + /// was used for processing instructions of a computer program or operating system. double readCPUTime() const; /// \brief Function for counting the number of CPU cycles (machine cycles). @@ -106,7 +113,7 @@ class Timer /// \brief Saves information about the state of given timer. /// - /// Knows whether the timer is currently stopped or not. + /// Knows whether the timer is currently stopped or it is running. bool stopState; /// \brief Time Stamp Counter returning number of CPU cycles since reset. -- GitLab From 85aae0730048a0ad1115e639e3fc6c17b823851c Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Wed, 21 Nov 2018 13:33:54 +0100 Subject: [PATCH 089/111] Added Logger documentation. --- src/TNL/Containers/List.h | 1 + src/TNL/Logger.h | 20 +++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/TNL/Containers/List.h b/src/TNL/Containers/List.h index 3954b014e..96cd236f7 100644 --- a/src/TNL/Containers/List.h +++ b/src/TNL/Containers/List.h @@ -59,6 +59,7 @@ template< class T > class List /// Destroys the list. References to the values in the list become invalid. ~List(); + /// Returns the type of list. static String getType(); /// Returns \e true if the list contains no items, otherwise returns \e false. diff --git a/src/TNL/Logger.h b/src/TNL/Logger.h index bddcfeeeb..d73594d2c 100644 --- a/src/TNL/Logger.h +++ b/src/TNL/Logger.h @@ -15,7 +15,7 @@ namespace TNL { -/// Vytvari tabulku s logem vypoctu +/// Creates calculations log in the form of a table. class Logger { public: @@ -36,12 +36,12 @@ class Logger /// \param title String containing the header title. void writeHeader( const String& title ); - /// \brief Creates separator for structuring the log. + /// \brief Creates separator used as a log structure. void writeSeparator(); /// \brief Inserts information about various system parameters into the log. /// - /// \param parameters is a container with configuration parameters + /// \param parameters A container with configuration parameters. bool writeSystemInformation( const Config::ParameterContainer& parameters ); ///// @@ -50,6 +50,14 @@ class Logger /// \param label Label to be printed to the log together with the current time. void writeCurrentTime( const char* label ); + /// \brief Inserts parameter information into the log. + /// + /// \tparam ParameterType Type of the parameter. + /// \param label Description/label of the line. + /// \param parameterName Name of the parameter. + /// \param parameters A container with configuration parameters. + /// \param parameterLevel Integer defining the indent used in the log. + // TODO: add units template< typename ParameterType > void writeParameter( const String& label, @@ -57,6 +65,12 @@ class Logger const Config::ParameterContainer& parameters, int parameterLevel = 0 ); + /// \brief Inserts parameter information into the log. + /// + /// \tparam ParameterType Type of the parameter. + /// \param label Description/label of the line. + /// \param value Parameter value. + /// \param parameterLevel Integer defining the indent used in the log. template< typename ParameterType > void writeParameter( const String& label, const ParameterType& value, -- GitLab From 4bbbe44c1c5a3bf2b37b9016d11438d609411f83 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 26 Nov 2018 12:23:41 +0100 Subject: [PATCH 090/111] Fixed Logger documentation. --- src/TNL/Logger.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/TNL/Logger.h b/src/TNL/Logger.h index d73594d2c..7a6472bfa 100644 --- a/src/TNL/Logger.h +++ b/src/TNL/Logger.h @@ -33,7 +33,7 @@ class Logger /// /// The header usually contains title of the program. /// - /// \param title String containing the header title. + /// \param title A String containing the header title. void writeHeader( const String& title ); /// \brief Creates separator used as a log structure. @@ -78,8 +78,10 @@ class Logger protected: + /// \brief Integer defining the width of the log. int width; + /// \brief Output stream where the log will be printed out. std::ostream& stream; }; -- GitLab From 40b6779810466bf06978a0a11365521443cc98c1 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 26 Nov 2018 12:56:52 +0100 Subject: [PATCH 091/111] Fixed File documentation. --- src/TNL/File.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/TNL/File.h b/src/TNL/File.h index 20fb1fe7b..afa5631f6 100644 --- a/src/TNL/File.h +++ b/src/TNL/File.h @@ -66,12 +66,13 @@ class File ~File(); ///// - /// \brief Opens given file. + /// \brief Attempts to open given file and returns \e true after the file is + /// successfully opened. Otherwise returns \e false. /// /// Opens file with given \e fileName and returns true/false based on the success in opening the file. /// \param fileName String which indicates name of the file user wants to open. /// \param mode Indicates what user needs to do with opened file. - /// Modes to choose: IOMode::read or IOMode::write or IOMode::undefined. + /// Modes to choose: IOMode::read, IOMode::write or IOMode::undefined. bool open( const String& fileName, const IOMode mode ); @@ -81,13 +82,13 @@ class File return this->fileName; } - /// Returns number of read elements. + /// \brief Returns number of read elements. long int getReadElements() const { return this->readElements; } - /// Returns number of written elements. + /// \brief Returns number of written elements. long int getWrittenElements() const { return this->writtenElements; @@ -112,12 +113,12 @@ class File /// \brief Method that can write particular data type from CPU into given file. (Function that writes particular elements into given file.) /// - /// Returns boolean value based on the succes in writing elements into given file. + /// Returns \e true when the elements are successfully written into given file. Otherwise returns \e false. /// /// \tparam Type Type of data. - /// \tparam Device Place from where data are loaded before writing into file. For example Devices::Host or Devices::Cuda. + /// \tparam Device Place from where the data are loaded before writing into file. For example Devices::Host or Devices::Cuda. /// \tparam Index Type of index by which the elements are indexed. - /// \param buffer Pointer in memory from where the elements are loaded before writing into file. + /// \param buffer Pointer in memory where the elements are loaded from before writing into file. /// \param elements Number of elements the user wants to write into the given file. template< typename Type, typename Device = Devices::Host, typename Index = int > bool write( const Type* buffer, @@ -127,7 +128,8 @@ class File template< typename Type, typename Device = Devices::Host > bool write( const Type* buffer ); - /// \brief Closes given file and returns true/false based on the success in closing the file. + /// \brief Attempts to close given file and returns \e true when the file is + /// successfully closed. Otherwise returns \e false. bool close(); protected: -- GitLab From 8e1138bb89c59c64fdf8c2c281b6f38a79ae4339 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 26 Nov 2018 13:41:39 +0100 Subject: [PATCH 092/111] Fixed String documentation. --- src/TNL/String.h | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/TNL/String.h b/src/TNL/String.h index b503c4d28..2365a36e3 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -48,6 +48,7 @@ class String /// Constructs a string initialized with the 8-bit string \e c, excluding /// the given number of \e prefix_cut_off and \e sufix_cut_off characters. /// + /// @param c Pointer to an array of characters. /// @param prefix_cut_off Determines the length of the prefix that is going /// to be omitted from the string \e c. /// @param sufix_cut_off Determines the length of the sufix that is going @@ -56,13 +57,14 @@ class String int prefix_cut_off = 0, int sufix_cut_off = 0 ); - /// Returns type of string - String. + /// \brief Returns type of string - String. static String getType(); ///// /// \brief Copy constructor. /// /// Constructs a copy of the string \e str. + /// @param str Another string object, whose value is copied. String( const String& str ); /// \brief Converts anything to a string. @@ -92,7 +94,7 @@ class String /// \include StringExampleGetSize.out int getSize() const; - /// Returns size of allocated storage for given string. + /// \brief Returns size of allocated storage for given string. /// /// \par Example /// \include StringExampleGetAllocatedSize.cpp @@ -171,23 +173,23 @@ class String ///// // Operators for Strings. - /// This function assigns \e str to this string and returns a reference to + /// \brief This function assigns \e str to this string and returns a reference to /// this string. String& operator=( const String& str ); - /// This function appends the string \e str onto the end of this string + /// \brief This function appends the string \e str onto the end of this string /// and returns a reference to this string. String& operator+=( const String& str ); - /// This function concatenates strings \e str and returns a newly + /// \brief This function concatenates strings \e str and returns a newly /// constructed string object. String operator+( const String& str ) const; /// \brief This function overloads operator==(). /// - /// It returns \c true if this string is equal to \e str, otherwise returns + /// Returns \c true if this string is equal to \e str, otherwise returns /// \c false. bool operator==( const String& str ) const; /// \brief This function overloads operator!=(). /// - /// It returns \c true if this string is not equal to \e str, otherwise + /// Returns \c true if this string is not equal to \e str, otherwise /// returns \c false. bool operator!=( const String& str ) const; @@ -196,15 +198,15 @@ class String /// \brief This function overloads operator=(). /// - /// It assigns character \e str to this string. + /// Assigns character \e str to this string. String& operator=( char str ); /// \brief This function overloads operator+=(). /// - /// It appends character \e str to this string. + /// Appends character \e str to this string. String& operator+=( char str ); - // This function concatenates strings and returns a newly constructed string object. + // \brief This function concatenates strings and returns a newly constructed string object. String operator+( char str ) const; - // This function concatenates strings and returns a newly constructed string object. + // \brief This function concatenates strings and returns a newly constructed string object. bool operator==( char str ) const; /// \brief This function overloads operator!=(). bool operator!=( char str ) const; @@ -276,21 +278,21 @@ class String protected: - /// Pointer to char ended with zero byte + /// \brief Pointer to char ended with zero byte. char* string; - /// Length of allocated piece of memory. + /// \brief Length of allocated piece of memory. int length; }; // class String -/// Returns concatenation of \e string1 and \e string2. +/// \brief Returns concatenation of \e string1 and \e string2. String operator+( char string1, const String& string2 ); -/// Returns concatenation of \e string1 and \e string2. +/// \brief Returns concatenation of \e string1 and \e string2. String operator+( const char* string1, const String& string2 ); -/// Performs the string output to a stream +/// \brief Performs the string output to a stream std::ostream& operator<<( std::ostream& stream, const String& str ); template< typename T > -- GitLab From 3d8b8d30d7ab2b17feb5b8f6b7b126c7e8625349 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 26 Nov 2018 13:47:06 +0100 Subject: [PATCH 093/111] Fixed Timer documentation. --- src/TNL/Timer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TNL/Timer.h b/src/TNL/Timer.h index 05a6de3ed..bcbeaca28 100644 --- a/src/TNL/Timer.h +++ b/src/TNL/Timer.h @@ -60,7 +60,7 @@ class Timer /// It returns the elapsed time (in seconds) between calling the start() and stop() methods. /// Starts counting the real time after the method start() is called and /// pauses when the method stop() is called. - /// If the timer have been started more then once without resetting, + /// If the timer has been started more then once without resetting, /// the real time is counted by adding all intervals (between start and stop /// methods) together. /// This function can be called while the timer is running, there is no -- GitLab From 79dc0e4b59ad3291e74151f2c86d669e178bfe3f Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 26 Nov 2018 13:55:24 +0100 Subject: [PATCH 094/111] Fixed FileName documentation. --- src/TNL/FileName.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/TNL/FileName.h b/src/TNL/FileName.h index 601ced042..9642e570d 100644 --- a/src/TNL/FileName.h +++ b/src/TNL/FileName.h @@ -18,6 +18,9 @@ String getFileExtension( const String fileName ); void removeFileExtension( String& file_name ); +/// \brief Class for creating the full name of a file. +/// +/// Merges base name, index number and extention to create the full name of a file. class FileName { public: @@ -42,7 +45,7 @@ class FileName /// \brief Sets the extension of given file. /// /// Sets \e extension as suffix of a file name. - /// @param extension String that specifies extension of file (without dot). + /// @param extension A String that specifies extension of file (without dot). /// Suffix of a file name. E.g. doc, xls, tnl. void setExtension( const String& extension ); @@ -63,7 +66,7 @@ class FileName template< typename Coordinates > void setDistributedSystemNodeId( const Coordinates& nodeId ); - /// Creates appropriate name for given file. + /// \brief Creates appropriate name for given file. /// /// Creates particular file name using \e fileNameBase, \e digitsCount, /// \e index and \e extension. -- GitLab From 6ece880f5edbc9470f920b857309be9b6f6af703 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 26 Nov 2018 16:00:35 +0100 Subject: [PATCH 095/111] Started with Math and ParameterContainer documentation. --- src/TNL/Config/ParameterContainer.h | 9 +++++++++ src/TNL/Math.h | 27 ++++++++++++++++++--------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/TNL/Config/ParameterContainer.h b/src/TNL/Config/ParameterContainer.h index 2450c3809..55ef460d1 100644 --- a/src/TNL/Config/ParameterContainer.h +++ b/src/TNL/Config/ParameterContainer.h @@ -44,8 +44,17 @@ class ParameterContainer { public: + /** + * \brief Basic constructor. + */ ParameterContainer(); + /** + * \brief Adds parameter + * @tparam T Type of parameter value. + * @param name Name of the parameter. + * @param value Value assigned to the parameter. + */ template< class T > bool addParameter( const String& name, const T& value ); diff --git a/src/TNL/Math.h b/src/TNL/Math.h index 67e9f5e08..b32244c9c 100644 --- a/src/TNL/Math.h +++ b/src/TNL/Math.h @@ -19,7 +19,7 @@ namespace TNL { /*** - * This function returns minimum of two numbers. + * \brief This function returns minimum of two numbers. * GPU device code uses the functions defined in the CUDA's math_functions.h, * MIC uses trivial override and host uses the STL functions. */ @@ -43,7 +43,7 @@ ResultType min( const T1& a, const T2& b ) /*** - * This function returns maximum of two numbers. + * \brief This function returns maximum of two numbers. * GPU device code uses the functions defined in the CUDA's math_functions.h, * MIC uses trivial override and host uses the STL functions. */ @@ -66,7 +66,7 @@ ResultType max( const T1& a, const T2& b ) } /*** - * This function returns absolute value of given number. + * \brief This function returns absolute value of given number. */ template< class T > __cuda_callable__ inline @@ -87,7 +87,7 @@ T abs( const T& n ) } /*** - * This function returns argument of minimum of two numbers. + * \brief This function returns argument of minimum of two numbers. */ template< typename T1, typename T2, typename ResultType = typename std::common_type< T1, T2 >::type > __cuda_callable__ inline @@ -97,7 +97,7 @@ ResultType argMin( const T1& a, const T2& b ) } /*** - * This function returns argument of maximum of two numbers. + * \brief This function returns argument of maximum of two numbers. */ template< typename T1, typename T2, typename ResultType = typename std::common_type< T1, T2 >::type > __cuda_callable__ @@ -107,7 +107,7 @@ ResultType argMax( const T1& a, const T2& b ) } /*** - * This function returns argument of minimum of absolute values of two numbers. + * \brief This function returns argument of minimum of absolute values of two numbers. */ template< typename T1, typename T2, typename ResultType = typename std::common_type< T1, T2 >::type > __cuda_callable__ inline @@ -117,7 +117,7 @@ ResultType argAbsMin( const T1& a, const T2& b ) } /*** - * This function returns argument of maximum of absolute values of two numbers. + * \brief This function returns argument of maximum of absolute values of two numbers. */ template< typename T1, typename T2, typename ResultType = typename std::common_type< T1, T2 >::type > __cuda_callable__ @@ -137,7 +137,9 @@ ResultType pow( const T1& base, const T2& exp ) #endif } - +/** + * \brief This function returns square root of a value. + */ template< typename T > __cuda_callable__ inline T sqrt( const T& value ) @@ -149,7 +151,9 @@ T sqrt( const T& value ) #endif } - +/** + * \brief This function swaps values of two parameters. + */ template< typename Type > __cuda_callable__ void swap( Type& a, Type& b ) @@ -159,6 +163,11 @@ void swap( Type& a, Type& b ) b = tmp; } +/** + * \brief This function represents the signum function. + * + * It extracts the sign of a real number. + */ template< class T > __cuda_callable__ T sign( const T& a ) -- GitLab From 4fa8754911e57c26db947f5754bab660f601b1d8 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Wed, 28 Nov 2018 13:37:49 +0100 Subject: [PATCH 096/111] Added documentation of Math, Assert and ParameterContainer. --- src/TNL/Assert.h | 7 ++++++ src/TNL/Config/ParameterContainer.h | 29 ++++++++++++++++++---- src/TNL/Math.h | 37 +++++++++++++++++++++++++---- src/TNL/Object.h | 5 ++-- 4 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/TNL/Assert.h b/src/TNL/Assert.h index 6d13e35b1..34b721fe6 100644 --- a/src/TNL/Assert.h +++ b/src/TNL/Assert.h @@ -33,6 +33,13 @@ #if defined(NDEBUG) || defined(HAVE_MIC) // empty macros for optimized build +/** + * \brief Assert that the expression \e val evaluates to \e true. + * + * The assertion succeeds if, and only if, \e val evaluates to equal to \e true. + * On success the test continues without any side effects. + * On failure the test is terminated with the error message \e msg. + */ #define TNL_ASSERT_TRUE( val, msg ) #define TNL_ASSERT_FALSE( val, msg ) #define TNL_ASSERT_EQ( val1, val2, msg ) diff --git a/src/TNL/Config/ParameterContainer.h b/src/TNL/Config/ParameterContainer.h index 55ef460d1..f524d2917 100644 --- a/src/TNL/Config/ParameterContainer.h +++ b/src/TNL/Config/ParameterContainer.h @@ -50,10 +50,11 @@ class ParameterContainer ParameterContainer(); /** - * \brief Adds parameter - * @tparam T Type of parameter value. - * @param name Name of the parameter. - * @param value Value assigned to the parameter. + * \brief Adds new parameter to the ParameterContainer. + * + * \tparam T Type of parameter value. + * \param name Name of the new parameter. + * \param value Value assigned to the parameter. */ template< class T > bool addParameter( const String& name, const T& value ); @@ -61,8 +62,20 @@ class ParameterContainer bool addParameter( const String& name, const String& value ); + /** + * \brief Checks whether the parameter \e name already exists in ParameterContainer. + * + * \param name Name of the parameter. + */ bool checkParameter( const String& name ) const; + /** + * \brief Assigns new \e value to the parameter \e name. + * + * \tparam T Type of the parameter value. + * \param name Name of parameter. + * \param value Value of type T assigned to the parameter. + */ template< class T > bool setParameter( const String& name, const T& value ); @@ -89,6 +102,11 @@ class ParameterContainer return false; } + /** + * \brief Returns parameter value. + * + * \param name Name of parameter. + */ template< class T > const T& getParameter( const String& name ) const { int i; @@ -104,6 +122,9 @@ class ParameterContainer //! Broadcast to other nodes in MPI cluster // void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); + /** + * \brief Basic destructor. + */ ~ParameterContainer(); protected: diff --git a/src/TNL/Math.h b/src/TNL/Math.h index b32244c9c..34cd91eeb 100644 --- a/src/TNL/Math.h +++ b/src/TNL/Math.h @@ -20,6 +20,7 @@ namespace TNL { /*** * \brief This function returns minimum of two numbers. + * * GPU device code uses the functions defined in the CUDA's math_functions.h, * MIC uses trivial override and host uses the STL functions. */ @@ -44,6 +45,7 @@ ResultType min( const T1& a, const T2& b ) /*** * \brief This function returns maximum of two numbers. + * * GPU device code uses the functions defined in the CUDA's math_functions.h, * MIC uses trivial override and host uses the STL functions. */ @@ -65,8 +67,8 @@ ResultType max( const T1& a, const T2& b ) #endif } -/*** - * \brief This function returns absolute value of given number. +/** + * \brief This function returns absolute value of given number \e n. */ template< class T > __cuda_callable__ inline @@ -126,6 +128,9 @@ ResultType argAbsMax( const T1& a, const T2& b ) return ( TNL::abs( a ) > TNL::abs( b ) ) ? a : b; } +/** + * \brief This function returns the result of \e base to the power of \e exp. + */ template< typename T1, typename T2, typename ResultType = typename std::common_type< T1, T2 >::type > __cuda_callable__ inline ResultType pow( const T1& base, const T2& exp ) @@ -138,7 +143,7 @@ ResultType pow( const T1& base, const T2& exp ) } /** - * \brief This function returns square root of a value. + * \brief This function returns square root of the given \e value. */ template< typename T > __cuda_callable__ inline @@ -153,6 +158,8 @@ T sqrt( const T& value ) /** * \brief This function swaps values of two parameters. + * + * It assigns the value of \e a to the parameter \e b and vice versa. */ template< typename Type > __cuda_callable__ @@ -166,7 +173,9 @@ void swap( Type& a, Type& b ) /** * \brief This function represents the signum function. * - * It extracts the sign of a real number. + * It extracts the sign of the number \e a. In other words, the signum function projects + * negative numbers to value -1, positive numbers to value 1 and zero to value 0. + * Non-zero complex numbers are projected to the unit circle. */ template< class T > __cuda_callable__ @@ -177,6 +186,14 @@ T sign( const T& a ) return ( T ) 1; } +/** + * \brief This function tests whether the given real number is small. + * + * It tests whether the number \e v is in \e tolerance, in other words, whether + * \e v in absolute value is less then or equal to \e tolerance. + * @param v Real number. + * @param tolerance Critical value which is set to 0.00001 by defalt. + */ template< typename Real > __cuda_callable__ bool isSmall( const Real& v, @@ -185,12 +202,24 @@ bool isSmall( const Real& v, return ( -tolerance <= v && v <= tolerance ); } +/** + * \brief This function divides \e num by \e div and rounds up the result. + * + * @param num An integer considered as dividend. + * @param div An integer considered as divisor. + */ __cuda_callable__ inline int roundUpDivision( const int num, const int div ) { return num / div + ( num % div != 0 ); } +/** + * \brief This function rounds \e number to the nearest multiple of number \e multiple. + * + * @param number Integer we want to round. + * @param multiple Integer. + */ __cuda_callable__ inline int roundToMultiple( int number, int multiple ) { diff --git a/src/TNL/Object.h b/src/TNL/Object.h index 4b37d8a77..b4f225075 100644 --- a/src/TNL/Object.h +++ b/src/TNL/Object.h @@ -17,8 +17,9 @@ namespace TNL { -//! This is basic class for all 'large' objects like matrices, meshes, grids, solvers etc. -/*! +/** + * \brief This is the basic class for all 'large' objects like matrices, meshes, grids, solvers, etc.. + * * Objects like numerical grids, meshes, matrices large vectors etc. * are inherited by this class. This class provides name for such objects. Giving * a name to each bigger object is compulsory. The name can help to locate -- GitLab From 95eeae927a426ae4c6c1a49b265a4782f4ad0172 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Fri, 30 Nov 2018 15:35:38 +0100 Subject: [PATCH 097/111] Added Assert documentation. --- src/TNL/Assert.h | 57 +++++++++++++++++++++++++++++++++++++++++++++++- src/TNL/Math.h | 2 +- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/TNL/Assert.h b/src/TNL/Assert.h index 34b721fe6..dabd69a97 100644 --- a/src/TNL/Assert.h +++ b/src/TNL/Assert.h @@ -34,20 +34,75 @@ // empty macros for optimized build /** - * \brief Assert that the expression \e val evaluates to \e true. + * \brief Asserts that the expression \e val evaluates to \e true. * * The assertion succeeds if, and only if, \e val evaluates to equal to \e true. * On success the test continues without any side effects. * On failure the test is terminated with the error message \e msg. */ #define TNL_ASSERT_TRUE( val, msg ) +/** + * \brief Asserts that the expression \e val evaluates to \e false. + * + * The assertion succeeds if, and only if, \e val evaluates to equal to \e false. + * On success the test continues without any side effects. + * On failure the test is terminated with the error message \e msg. + */ #define TNL_ASSERT_FALSE( val, msg ) +/** + * \brief Asserts that the expression \e val1 is equal to \e val2. + * + * The assertion succeeds if, and only if, \e val1 and \e val2 are equal. + * On success the test continues without any side effects. + * On failure the test is terminated with the error message \e msg. + */ #define TNL_ASSERT_EQ( val1, val2, msg ) +/** + * \brief Asserts that the expression \e val1 is not equal to \e val2. + * + * The assertion succeeds if, and only if, \e val1 and \e val2 are not equal. + * On success the test continues without any side effects. + * On failure the test is terminated with the error message \e msg. + */ #define TNL_ASSERT_NE( val1, val2, msg ) +/** + * \brief Asserts that the expression \e val1 is less than or equal to \e val2. + * + * The assertion succeeds if, and only if, \e val1 is less than or equal to \e val2. + * On success the test continues without any side effects. + * On failure the test is terminated with the error message \e msg. + */ #define TNL_ASSERT_LE( val1, val2, msg ) +/** + * \brief Asserts that the expression \e val1 is less than \e val2. + * + * The assertion succeeds if, and only if, \e val1 is less than \e val2. + * On success the test continues without any side effects. + * On failure the test is terminated with the error message \e msg. + */ #define TNL_ASSERT_LT( val1, val2, msg ) +/** + * \brief Asserts that the expression \e val1 is greater than or equal to \e val2. + * + * The assertion succeeds if, and only if, \e val1 is greater than or equal to \e val2. + * On success the test continues without any side effects. + * On failure the test is terminated with the error message \e msg. + */ #define TNL_ASSERT_GE( val1, val2, msg ) +/** + * \brief Asserts that the expression \e val1 is greater than \e val2. + * + * The assertion succeeds if, and only if, \e val1 is greater than \e val2. + * On success the test continues without any side effects. + * On failure the test is terminated with the error message \e msg. + */ #define TNL_ASSERT_GT( val1, val2, msg ) +/** + * \brief Asserts that the specified \e ___tnl__assert_condition is valid. + * + * The assertion succeeds if, and only if, ___tnl__assert_condition is valid. + * On success the test continues without any side effects. + * On failure the test is terminated with the error message \e ___tnl__assert_command. #define TNL_ASSERT( ___tnl__assert_condition, ___tnl__assert_command ) #else /* #ifdef NDEBUG */ diff --git a/src/TNL/Math.h b/src/TNL/Math.h index 34cd91eeb..12cab18d8 100644 --- a/src/TNL/Math.h +++ b/src/TNL/Math.h @@ -215,7 +215,7 @@ inline int roundUpDivision( const int num, const int div ) } /** - * \brief This function rounds \e number to the nearest multiple of number \e multiple. + * \brief This function rounds up \e number to the nearest multiple of number \e multiple. * * @param number Integer we want to round. * @param multiple Integer. -- GitLab From 8baf2486085fd4da972e69fd806848d406633456 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Fri, 30 Nov 2018 16:01:42 +0100 Subject: [PATCH 098/111] Modified the ParameterContainer documentation. --- src/TNL/Config/ParameterContainer.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/TNL/Config/ParameterContainer.h b/src/TNL/Config/ParameterContainer.h index f524d2917..b475c53ec 100644 --- a/src/TNL/Config/ParameterContainer.h +++ b/src/TNL/Config/ParameterContainer.h @@ -82,6 +82,17 @@ class ParameterContainer bool setParameter( const String& name, const String& value ); + /** + * \brief Checks whether the parameter \e name is given the \e value. + * + * Returns \e true if the parameter \e name is given the \e value. + * If the parameter does not have any value or has different value then the given + * \e value the method returns \e false and shows message when \e verbose is \e true. + * + * @param name Name of parameter. + * @param value Value of type T we want to check whether is assigned to the parameter. + * @param verbose Boolean value defining whether to show error message (when true) or not (when false). + */ template< class T > bool getParameter( const String& name, T& value, bool verbose = true ) const -- GitLab From c6a549f1c97fb170bed71066dde949600d999a3b Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 3 Dec 2018 10:26:47 +0100 Subject: [PATCH 099/111] Improved documentation of Containers/List. --- src/TNL/Containers/List.h | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/TNL/Containers/List.h b/src/TNL/Containers/List.h index 96cd236f7..68e521a62 100644 --- a/src/TNL/Containers/List.h +++ b/src/TNL/Containers/List.h @@ -26,9 +26,9 @@ template< class T > class ListDataElement; /*! To acces elements in the list one can use method getSize() and operator[](). To add elements there are methods Append(), Prepend() and Insert() to insert an element at given - position. To erase particular element there is merthod + position. To erase particular element there is method Erase() taking the element position. To erase all elements - there is method EraseAll. There are also alternatives DeepErase() + there is method reset(). There are also alternatives DeepErase() and DeepEraseAll() to free dynamicaly allocated data inside the data elements. The list stores pointer to last accesed element so if one goes @@ -51,7 +51,7 @@ template< class T > class List /// \brief Copy constructor. /// /// Construct a copy of \e list. - /// @param list Name of another list. + /// \param list Name of another list. List( const List& list ); /// \brief Destructor. @@ -96,18 +96,27 @@ template< class T > class List bool Insert( const T& data, const int& ind ); /// Appends copy of another list. + /// + /// \param lst Name of another list. bool AppendList( const List< T >& lst ); /// Prepends copy of another list. + /// + /// \param lst Name of another list. bool PrependList( const List< T >& lst ); + /// Transforms list to an \e array. template< typename Array > void toArray( Array& array ); /// Erases data element at given position. + /// + /// \param ind Index of the data element one chooses to remove. void Erase( const int& ind ); /// Erases data element with contained data at given position. + /// + /// \param ind Index of the data element one chooses to remove. void DeepErase( const int& ind ); /// Erases all data elements. @@ -119,15 +128,23 @@ template< class T > class List void DeepEraseAll(); /// Saves the list in binary format. + /// + /// \param file Name of file. bool Save( File& file ) const; /// Saves the list in binary format using method save of type T. + /// + /// \param file Name of file. bool DeepSave( File& file ) const; - /// Loads the list. + /// Loads the list from file. + /// + /// \param file Name of file. bool Load( File& file ); - /// Loads the list using method Load of the type T. + /// Loads the list from file using method Load of the type T. + /// + /// \param file Name of file. bool DeepLoad( File& file ); protected: -- GitLab From 0c7cf446f4e3a91893466ba72919a1136ee896bc Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 3 Dec 2018 11:17:39 +0100 Subject: [PATCH 100/111] Added Object documentation. --- src/TNL/Object.h | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/TNL/Object.h b/src/TNL/Object.h index b4f225075..f0b2b435f 100644 --- a/src/TNL/Object.h +++ b/src/TNL/Object.h @@ -34,16 +34,18 @@ class Object public: /**** - * Type getter. This returns the type in C++ style - for example the returned value + * \brief Type getter. + * + * Returns the type in C++ style - for example the returned value * may look as follows: "Vector< double, Devices::Cuda >". */ - static String getType(); virtual String getTypeVirtual() const; /**** - * This is used for load and save methods. + * \brief This is used for load and save methods. + * * Each object is saved as if it was stored on Devices::Host. So even Vector< double, Devices::Cuda > * is saved as Vector< double, Devices::Host >. */ @@ -51,13 +53,25 @@ class Object virtual String getSerializationTypeVirtual() const; - //! Method for saving the object to a file as a binary data + /*** + * \brief Method for saving the object to a file as a binary data. + * + * \param file Name of file object. + */ virtual bool save( File& file ) const; - //! Method for restoring the object from a file + /*** + * \brief Method for restoring the object from a file. + * + * \param file Name of file object. + */ virtual bool load( File& file ); - //! Method for restoring the object from a file + /*** + * \brief Method for restoring the object from a file. + * + * \param file Name of file object. + */ virtual bool boundLoad( File& file ); bool save( const String& fileName ) const; @@ -66,7 +80,7 @@ class Object bool boundLoad( const String& fileName ); - //! Destructor + /// Destructor. // FIXME: __cuda_callable__ would have to be added to every overriding destructor, // even if the object's constructor is not __cuda_callable__ // __cuda_callable__ -- GitLab From 255c918529ebe95e83c2e37db9429e8d629dff15 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Mon, 3 Dec 2018 13:59:27 +0100 Subject: [PATCH 101/111] Added ConfigDescription documentation and added small changes in Object, Math and ParameterContainer. --- src/TNL/Config/ConfigDescription.h | 52 ++++++++++++++++++++++++++++- src/TNL/Config/ParameterContainer.h | 6 ++-- src/TNL/Math.h | 28 +++++++++++----- src/TNL/Object.h | 10 +++--- 4 files changed, 79 insertions(+), 17 deletions(-) diff --git a/src/TNL/Config/ConfigDescription.h b/src/TNL/Config/ConfigDescription.h index 37325183b..d19386958 100644 --- a/src/TNL/Config/ConfigDescription.h +++ b/src/TNL/Config/ConfigDescription.h @@ -27,8 +27,18 @@ class ConfigDescription { public: + /** + * \brief Basic constructor. + */ ConfigDescription(); + /** + * \brief Adds new entry to the configuration description. + * + * \tparam EntryType Type of the entry. + * \param name Name of the entry. + * \param description More specific information about the entry. + */ template< typename EntryType > void addEntry( const String& name, const String& description ) @@ -37,6 +47,13 @@ class ConfigDescription entries.Append( currentEntry ); } + /** + * \brief Adds new entry to the configuration description. + * + * \tparam EntryType Type of the entry. + * \param name Name of the entry. + * \param description More specific information about the entry. + */ template< typename EntryType > void addRequiredEntry( const String& name, const String& description ) @@ -44,7 +61,15 @@ class ConfigDescription currentEntry = new ConfigEntry< EntryType >( name, description, true ); entries.Append( currentEntry ); } - + + /** + * \brief Adds new entry to the configuration description. + * + * \tparam EntryType Type of the entry. + * \param name Name of the entry. + * \param description More specific information about the entry. + * \param defaultValue Default value of the entry. + */ template< typename EntryType > void addEntry( const String& name, const String& description, @@ -57,6 +82,13 @@ class ConfigDescription entries. Append( currentEntry ); } + /** + * \brief Adds new list to the configuration description. + * + * \tparam EntryType Type of the list. + * \param name Name of the list. + * \param description More specific information about the list. + */ template< typename EntryType > void addList( const String& name, const String& description ) @@ -65,6 +97,13 @@ class ConfigDescription entries.Append( currentEntry ); } + /** + * \brief Adds new list to the configuration description. + * + * \tparam EntryType Type of the list. + * \param name Name of the list. + * \param description More specific information about the list. + */ template< typename EntryType > void addRequiredList( const String& name, const String& description ) @@ -73,6 +112,14 @@ class ConfigDescription entries.Append( currentEntry ); } + /** + * \brief Adds new list to the configuration description. + * + * \tparam EntryType Type of the list. + * \param name Name of the list. + * \param description More specific information about the list. + * \param defaultValue Default value of the list. + */ template< typename EntryType > void addList( const String& name, const String& description, @@ -162,6 +209,9 @@ class ConfigDescription //bool parseConfigDescription( const char* file_name ); + /** + * \brief Basic destructor. + */ ~ConfigDescription(); protected: diff --git a/src/TNL/Config/ParameterContainer.h b/src/TNL/Config/ParameterContainer.h index b475c53ec..aac0cb6ab 100644 --- a/src/TNL/Config/ParameterContainer.h +++ b/src/TNL/Config/ParameterContainer.h @@ -89,9 +89,9 @@ class ParameterContainer * If the parameter does not have any value or has different value then the given * \e value the method returns \e false and shows message when \e verbose is \e true. * - * @param name Name of parameter. - * @param value Value of type T we want to check whether is assigned to the parameter. - * @param verbose Boolean value defining whether to show error message (when true) or not (when false). + * \param name Name of parameter. + * \param value Value of type T we want to check whether is assigned to the parameter. + * \param verbose Boolean value defining whether to show error message (when true) or not (when false). */ template< class T > bool getParameter( const String& name, T& value, diff --git a/src/TNL/Math.h b/src/TNL/Math.h index 12cab18d8..68eb1f556 100644 --- a/src/TNL/Math.h +++ b/src/TNL/Math.h @@ -18,7 +18,7 @@ namespace TNL { -/*** +/** * \brief This function returns minimum of two numbers. * * GPU device code uses the functions defined in the CUDA's math_functions.h, @@ -43,7 +43,7 @@ ResultType min( const T1& a, const T2& b ) } -/*** +/** * \brief This function returns maximum of two numbers. * * GPU device code uses the functions defined in the CUDA's math_functions.h, @@ -191,8 +191,8 @@ T sign( const T& a ) * * It tests whether the number \e v is in \e tolerance, in other words, whether * \e v in absolute value is less then or equal to \e tolerance. - * @param v Real number. - * @param tolerance Critical value which is set to 0.00001 by defalt. + * \param v Real number. + * \param tolerance Critical value which is set to 0.00001 by defalt. */ template< typename Real > __cuda_callable__ @@ -205,8 +205,8 @@ bool isSmall( const Real& v, /** * \brief This function divides \e num by \e div and rounds up the result. * - * @param num An integer considered as dividend. - * @param div An integer considered as divisor. + * \param num An integer considered as dividend. + * \param div An integer considered as divisor. */ __cuda_callable__ inline int roundUpDivision( const int num, const int div ) @@ -217,8 +217,8 @@ inline int roundUpDivision( const int num, const int div ) /** * \brief This function rounds up \e number to the nearest multiple of number \e multiple. * - * @param number Integer we want to round. - * @param multiple Integer. + * \param number Integer we want to round. + * \param multiple Integer. */ __cuda_callable__ inline int roundToMultiple( int number, int multiple ) @@ -226,12 +226,24 @@ inline int roundToMultiple( int number, int multiple ) return multiple*( number/ multiple + ( number % multiple != 0 ) ); } +/** + * \brief This function checks if \e x is an integral power of two. + * + * Returns \e true if \e x is a power of two. Otherwise returns \e false. + * \param x Integer. + */ __cuda_callable__ inline bool isPow2( int x ) { return ( ( x & ( x - 1 ) ) == 0 ); } +/** + * \brief This function checks if \e x is an integral power of two. + * + * Returns \e true if \e x is a power of two. Otherwise returns \e false. + * \param x Long integer. + */ __cuda_callable__ inline bool isPow2( long int x ) { diff --git a/src/TNL/Object.h b/src/TNL/Object.h index f0b2b435f..9725d1db5 100644 --- a/src/TNL/Object.h +++ b/src/TNL/Object.h @@ -33,7 +33,7 @@ class Object { public: - /**** + /** * \brief Type getter. * * Returns the type in C++ style - for example the returned value @@ -43,7 +43,7 @@ class Object virtual String getTypeVirtual() const; - /**** + /** * \brief This is used for load and save methods. * * Each object is saved as if it was stored on Devices::Host. So even Vector< double, Devices::Cuda > @@ -53,21 +53,21 @@ class Object virtual String getSerializationTypeVirtual() const; - /*** + /** * \brief Method for saving the object to a file as a binary data. * * \param file Name of file object. */ virtual bool save( File& file ) const; - /*** + /** * \brief Method for restoring the object from a file. * * \param file Name of file object. */ virtual bool load( File& file ); - /*** + /** * \brief Method for restoring the object from a file. * * \param file Name of file object. -- GitLab From 6e4ed25d40d187aa566f68c05fd43bc17f50fde2 Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber Date: Tue, 4 Dec 2018 10:37:06 +0100 Subject: [PATCH 102/111] Fixed unclosed comment in Assert.h Added examples to CMakeList.txt. --- src/Examples/CMakeLists.txt | 6 ++++++ src/TNL/Assert.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/Examples/CMakeLists.txt b/src/Examples/CMakeLists.txt index b8e7c574a..f15836344 100644 --- a/src/Examples/CMakeLists.txt +++ b/src/Examples/CMakeLists.txt @@ -24,5 +24,11 @@ target_link_libraries( FileExample tnl ) ADD_EXECUTABLE( StringExample StringExample.cpp ) target_link_libraries( StringExample tnl ) +ADD_EXECUTABLE( StringExampleGetSize StringExampleGetSize.cpp ) +target_link_libraries( StringExampleGetSize tnl ) + +ADD_EXECUTABLE( StringExampleGetAllocatedSize StringExampleGetAllocatedSize.cpp ) +target_link_libraries( StringExampleGetAllocatedSize tnl ) + ADD_EXECUTABLE( TimerExample TimerExample.cpp ) target_link_libraries( TimerExample tnl ) \ No newline at end of file diff --git a/src/TNL/Assert.h b/src/TNL/Assert.h index dabd69a97..d601f9c1b 100644 --- a/src/TNL/Assert.h +++ b/src/TNL/Assert.h @@ -103,6 +103,7 @@ * The assertion succeeds if, and only if, ___tnl__assert_condition is valid. * On success the test continues without any side effects. * On failure the test is terminated with the error message \e ___tnl__assert_command. + */ #define TNL_ASSERT( ___tnl__assert_condition, ___tnl__assert_command ) #else /* #ifdef NDEBUG */ -- GitLab From 3749c70dd0f97f0b99250c396deeddec589cda88 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Wed, 12 Dec 2018 16:01:46 +0100 Subject: [PATCH 103/111] Modiefied String and Array documentations. --- src/TNL/Containers/Array.h | 17 ++++++++++++++--- src/TNL/Containers/List.h | 2 +- src/TNL/String.h | 6 ++++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/TNL/Containers/Array.h b/src/TNL/Containers/Array.h index 8d43a979b..d188d84f7 100644 --- a/src/TNL/Containers/Array.h +++ b/src/TNL/Containers/Array.h @@ -21,6 +21,10 @@ template< int, typename > class StaticArray; /** * Array handles memory allocation and sharing of the same data between more Arrays. + * + * \tparam Value Type of array values. + * \tparam Device Device type. + * \tparam Index Type of index. */ template< typename Value, typename Device = Devices::Host, @@ -35,7 +39,10 @@ class Array : public Object typedef Containers::Array< Value, Devices::Host, Index > HostType; typedef Containers::Array< Value, Devices::Cuda, Index > CudaType; - /** \brief Basic constructor. */ + /** \brief Basic constructor. + * + * Constructs an empty array with the size of zero. + */ Array(); /** @@ -113,7 +120,7 @@ class Array : public Object template< int Size > void bind( StaticArray< Size, Value >& array ); - /** + /** * \brief Swaps all features of given array with existing \e array. * * Swaps sizes, all values (data), allocated memory and references of given @@ -168,14 +175,18 @@ class Array : public Object */ __cuda_callable__ inline const Value& operator[] ( const Index& i ) const; + /** Assigns \e array to the given array, replacing its current contents. */ Array& operator = ( const Array& array ); + /** Assigns \e array to the given array, replacing its current contents. */ template< typename ArrayT > Array& operator = ( const ArrayT& array ); + /** \brief This function checks whether the given array is equal to \e array. */ template< typename ArrayT > bool operator == ( const ArrayT& array ) const; + /** \brief This function checks whether the given array is not equal to \e array. */ template< typename ArrayT > bool operator != ( const ArrayT& array ) const; @@ -253,7 +264,7 @@ class Array : public Object * \brief Pointer to the originally allocated data. * * They might differ if one long array is partitioned into more shorter - * arrays. Each of them must know the pointer on allocated data because + * arrays. Each of them must know the pointer on allocated data because * the last one must deallocate the array. If outer data (not allocated * by TNL) are bind then this pointer is zero since no deallocation is * necessary. diff --git a/src/TNL/Containers/List.h b/src/TNL/Containers/List.h index 68e521a62..2c175bcce 100644 --- a/src/TNL/Containers/List.h +++ b/src/TNL/Containers/List.h @@ -22,7 +22,7 @@ namespace Containers { template< class T > class ListDataElement; -//! Template for double linked lists +/// \brief Template for double linked lists /*! To acces elements in the list one can use method getSize() and operator[](). To add elements there are methods Append(), Prepend() and Insert() to insert an element at given diff --git a/src/TNL/String.h b/src/TNL/String.h index 0730af6f6..838b27e98 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -208,9 +208,11 @@ class String /// /// Appends character \e str to this string. String& operator+=( char str ); - // \brief This function concatenates strings and returns a newly constructed string object. + /// \brief This function concatenates strings and returns a newly constructed string object. String operator+( char str ) const; - // \brief This function concatenates strings and returns a newly constructed string object. + /// \brief This function checks whether the given string is equal to \e str. + /// + /// It returns \e true when the given string is equal to \e str. Otherwise returns \e false. bool operator==( char str ) const; /// \brief This function overloads operator!=(). bool operator!=( char str ) const; -- GitLab From 27eeb54508969bba7cdc8b88890fc230b0421317 Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber Date: Thu, 13 Dec 2018 10:24:32 +0100 Subject: [PATCH 104/111] Removed unnecessary contructors. --- src/TNL/String.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/TNL/String.cpp b/src/TNL/String.cpp index 292d90c0a..817c62cca 100644 --- a/src/TNL/String.cpp +++ b/src/TNL/String.cpp @@ -29,12 +29,6 @@ String::String() setString( nullptr ); } -String::String( const char* str ) - : string( nullptr ), length( 0 ) -{ - setString( str ); -} - String::String( const char* c, int prefix_cut_off, int sufix_cut_off ) : string( nullptr ), length( 0 ) { @@ -47,13 +41,6 @@ String::String( const String& str ) setString( str.getString() ); } -String::String( const bool b ) - : string( nullptr ), length( 0 ) -{ - if( b ) this->setString( "true" ); - else this->setString( "false" ); -} - String String::getType() { return String( "String" ); -- GitLab From bee4229b425031fc5efaa520a14a20f7fbd57805 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Thu, 13 Dec 2018 12:10:32 +0100 Subject: [PATCH 105/111] Corrected mistakes in all examples. --- src/Examples/CMakeLists.txt | 8 +++-- src/Examples/ConfigDescriptionExample.cpp | 4 +-- src/Examples/FileExample.cpp | 4 +-- src/Examples/ListExample.cpp | 11 ++++--- src/Examples/LoggerExample.cpp | 4 +-- src/Examples/MathExample.cpp | 4 +-- src/Examples/StringExample.cpp | 31 +++++++++++-------- .../StringExampleGetAllocatedSize.cpp | 6 ++-- src/Examples/StringExampleGetSize.cpp | 6 ++-- src/Examples/StringExampleSetSize.cpp | 9 ++++-- src/Examples/TimerExample.cpp | 5 +-- 11 files changed, 54 insertions(+), 38 deletions(-) diff --git a/src/Examples/CMakeLists.txt b/src/Examples/CMakeLists.txt index 4e787076c..502f90d8a 100644 --- a/src/Examples/CMakeLists.txt +++ b/src/Examples/CMakeLists.txt @@ -33,15 +33,17 @@ target_link_libraries( LoggerExample tnl ) ADD_EXECUTABLE( MathExample MathExample.cpp ) target_link_libraries( MathExample tnl ) - ADD_EXECUTABLE( StringExample StringExample.cpp ) target_link_libraries( StringExample tnl ) +ADD_EXECUTABLE( StringExampleGetAllocatedSize StringExampleGetAllocatedSize.cpp ) +target_link_libraries( StringExampleGetAllocatedSize tnl ) + ADD_EXECUTABLE( StringExampleGetSize StringExampleGetSize.cpp ) target_link_libraries( StringExampleGetSize tnl ) -ADD_EXECUTABLE( StringExampleGetAllocatedSize StringExampleGetAllocatedSize.cpp ) -target_link_libraries( StringExampleGetAllocatedSize tnl ) +ADD_EXECUTABLE( StringExampleSetSize StringExampleSetSize.cpp ) +target_link_libraries( StringExampleSetSize tnl ) ADD_EXECUTABLE( TimerExample TimerExample.cpp ) target_link_libraries( TimerExample tnl ) \ No newline at end of file diff --git a/src/Examples/ConfigDescriptionExample.cpp b/src/Examples/ConfigDescriptionExample.cpp index 6d7d48d90..59958f1d1 100644 --- a/src/Examples/ConfigDescriptionExample.cpp +++ b/src/Examples/ConfigDescriptionExample.cpp @@ -1,12 +1,12 @@ #include -#include +#include using namespace TNL; using namespace std; int main() { - ConfigDescription confd; + Config::ConfigDescription confd; confd.template addEntry< String >("--new-entry","Specific description."); confd.template addEntryEnum< String >("option1"); confd.template addEntryEnum< String >("option2"); diff --git a/src/Examples/FileExample.cpp b/src/Examples/FileExample.cpp index f5f3912dd..18b73ca78 100644 --- a/src/Examples/FileExample.cpp +++ b/src/Examples/FileExample.cpp @@ -7,7 +7,7 @@ using namespace std; int main() { - File file; + /*File file; file.open( String("new-file.tnl"), IOMode::write ); String title("Header"); @@ -19,6 +19,6 @@ int main() file.read( title2, 4); file.close(); - cout << "title2:" << title2 < -#include +#include +#include +#include using namespace TNL; using namespace std; int main() { - template List< int > lst; - List lst; + Containers::List< int > lst; lst.isEmpty(); lst.Append(1); @@ -18,6 +19,6 @@ int main() lst.Insert(2,1); - Array array; - lst.template toArray< int >(array); + Containers::Array array; + lst.toArray(array); } \ No newline at end of file diff --git a/src/Examples/LoggerExample.cpp b/src/Examples/LoggerExample.cpp index 9624502a2..cb4e3dc4a 100644 --- a/src/Examples/LoggerExample.cpp +++ b/src/Examples/LoggerExample.cpp @@ -1,13 +1,13 @@ #include #include -#include +#include using namespace TNL; using namespace std; int main() { - Logger logger(50,stream); + Logger logger(50,cout); Config::ParameterContainer parameters; logger.writeSystemInformation(parameters); diff --git a/src/Examples/MathExample.cpp b/src/Examples/MathExample.cpp index 4e8db0931..bb5e29b5e 100644 --- a/src/Examples/MathExample.cpp +++ b/src/Examples/MathExample.cpp @@ -1,5 +1,5 @@ #include -#include +#include using namespace TNL; using namespace std; @@ -7,5 +7,5 @@ using namespace std; int main() { isPow2(1024); - roundUpDevision(10,4); + roundUpDivision(10,4); } \ No newline at end of file diff --git a/src/Examples/StringExample.cpp b/src/Examples/StringExample.cpp index d6c45dee8..f69fe9f1f 100644 --- a/src/Examples/StringExample.cpp +++ b/src/Examples/StringExample.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include using namespace TNL; using namespace std; @@ -28,15 +30,16 @@ int main( int argc, char* argv[] ) size = str3.getSize(); cout << "size of string:" << size << "bytes" << endl;*/ - String str - setter = str.setString( "Something new" ); + String str; + str.setString( "Something new" ); + String setter = str; cout << "setter:" << setter << endl; const char* getter = str4.getString(); cout << "getter:" << getter << endl; String word( "computer" ) ; - third_letter = word[2]; + char third_letter = word[2]; cout << "third_letter:" << third_letter << endl; // Operators for C Strings @@ -60,7 +63,7 @@ int main( int argc, char* argv[] ) // Operators for Strings String d1( "Cheese" ); - d = d1; + String d = d1; cout << "d:" << d << endl; String e( "Mac&" ); @@ -108,25 +111,27 @@ int main( int argc, char* argv[] ) // replace String phrase( "Hakuna matata" ); - new_phrase = phrase.replace( "a", "u", 2 ); + String new_phrase = phrase.replace( "a", "u", 2 ); cout << "new_phrase:" << new_phrase << endl; // strip String names(" Josh Martin John Marley Charles "); - better_names = names.strip(); + String better_names = names.strip(); cout << "better_names:" << better_names << endl; // split String dates("3/4/2005;8/7/2011;11/12/2019"); - list_dates = dates.split( list, ';' ); - cout << "list_dates:" << list_dates << endl; + Containers::List list; + dates.split( list, ';' ); + cout << "list_dates:" << list << endl; // save - String("Header").save(my-file.tnl); // saves "Header" into file my-file.tnl + File myFile; + String("Header").save(myFile); // saves "Header" into myFile // load String strg; - strg.load(my-file.tnl); + strg.load(myFile); cout << "strg:" << strg << endl; // get line @@ -134,8 +139,8 @@ int main( int argc, char* argv[] ) text << "Hello!" << std::endl; text << "What's up?" << std::endl; - String str; - str.getLine( text ); - cout << "str:" << str << endl; + String string; + string.getLine( text ); + cout << "str:" << string << endl; } diff --git a/src/Examples/StringExampleGetAllocatedSize.cpp b/src/Examples/StringExampleGetAllocatedSize.cpp index 993ad3df4..ad616de67 100644 --- a/src/Examples/StringExampleGetAllocatedSize.cpp +++ b/src/Examples/StringExampleGetAllocatedSize.cpp @@ -1,10 +1,12 @@ #include +#include -using namespace TNL +using namespace TNL; +using namespace std; int main() { - String str("my world") + String str("my world"); int alloc_size = str.getAllocatedSize(); cout << "alloc_size:" << alloc_size << endl; } \ No newline at end of file diff --git a/src/Examples/StringExampleGetSize.cpp b/src/Examples/StringExampleGetSize.cpp index b2c30f63a..77fb499a4 100644 --- a/src/Examples/StringExampleGetSize.cpp +++ b/src/Examples/StringExampleGetSize.cpp @@ -1,10 +1,12 @@ #include +#include -using namespace TNL +using namespace TNL; +using namespace std; int main() { - String str("my world") + String str("my world"); int size = str.getSize(); cout << "size of string:" << size << "bytes" << endl; } diff --git a/src/Examples/StringExampleSetSize.cpp b/src/Examples/StringExampleSetSize.cpp index 2e53f88b6..8451295a7 100644 --- a/src/Examples/StringExampleSetSize.cpp +++ b/src/Examples/StringExampleSetSize.cpp @@ -1,10 +1,13 @@ #include +#include -using namespace TNL +using namespace TNL; +using namespace std; int main() { - int memory + String memory; memory.setSize( 256 ); - cout << "memory:" << memory << endl; + int memorysize = memory.getSize(); + cout << "memory:" << memorysize << endl; } diff --git a/src/Examples/TimerExample.cpp b/src/Examples/TimerExample.cpp index aa4036734..5d5a81454 100644 --- a/src/Examples/TimerExample.cpp +++ b/src/Examples/TimerExample.cpp @@ -1,5 +1,6 @@ #include #include +#include #include using namespace TNL; @@ -16,7 +17,7 @@ int main() time.reset(); cout << "after reset:" << time.getRealTime() << endl; // writeLog example - Logger log1(50,stream); - writeLog( log1, 0 ); + Logger log1(50,cout); + time.writeLog( log1, 0 ); } -- GitLab From 9cfd6a53c1c1cc121bfaf21f8573e4a4b77af195 Mon Sep 17 00:00:00 2001 From: Nina Dzugasova Date: Thu, 13 Dec 2018 14:43:51 +0100 Subject: [PATCH 106/111] Corrected FileExample. --- src/Examples/FileExample.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Examples/FileExample.cpp b/src/Examples/FileExample.cpp index 18b73ca78..4d379f4b1 100644 --- a/src/Examples/FileExample.cpp +++ b/src/Examples/FileExample.cpp @@ -7,18 +7,18 @@ using namespace std; int main() { - /*File file; + File file; file.open( String("new-file.tnl"), IOMode::write ); String title("Header"); - file.write( title ); + file.write( &title ); file.close(); file.open( String("new-file.tnl"), IOMode::read ); String title2; - file.read( title2, 4); + file.read( &title2, 4); file.close(); - cout << "title2:" << title2 < Date: Thu, 13 Dec 2018 15:18:20 +0100 Subject: [PATCH 107/111] Successfully ran. --- Doxyfile | 1 - src/Benchmarks/Benchmarks.h | 10 +++++----- .../DistSpMV/tnl-benchmark-distributed-spmv.h | 6 +++--- .../LinearSolvers/tnl-benchmark-linear-solvers.h | 6 +++--- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Doxyfile b/Doxyfile index 2e7eec18c..1b947de18 100644 --- a/Doxyfile +++ b/Doxyfile @@ -891,7 +891,6 @@ EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = */Communicators/* \ */Config/* \ - */Containers/* \ */Debugging/* \ */Devices/* \ */DistributedContainers/* \ diff --git a/src/Benchmarks/Benchmarks.h b/src/Benchmarks/Benchmarks.h index 2b8b28b89..de3727b21 100644 --- a/src/Benchmarks/Benchmarks.h +++ b/src/Benchmarks/Benchmarks.h @@ -508,12 +508,12 @@ Benchmark::MetadataMap getHardwareMetadata() ? Communicators::MpiCommunicator::GetSize( Communicators::MpiCommunicator::AllGroup ) : 1 }, #endif - { "OpenMP enabled", Devices::Host::isOMPEnabled() }, - { "OpenMP threads", Devices::Host::getMaxThreadsCount() }, + { "OpenMP enabled", String( Devices::Host::isOMPEnabled() ) }, + { "OpenMP threads", String( Devices::Host::getMaxThreadsCount() ) }, { "CPU model name", Devices::SystemInfo::getCPUModelName( cpu_id ) }, - { "CPU cores", Devices::SystemInfo::getNumberOfCores( cpu_id ) }, - { "CPU threads per core", Devices::SystemInfo::getNumberOfThreads( cpu_id ) / Devices::SystemInfo::getNumberOfCores( cpu_id ) }, - { "CPU max frequency (MHz)", Devices::SystemInfo::getCPUMaxFrequency( cpu_id ) / 1e3 }, + { "CPU cores", String( Devices::SystemInfo::getNumberOfCores( cpu_id ) ) }, + { "CPU threads per core", String( Devices::SystemInfo::getNumberOfThreads( cpu_id ) / Devices::SystemInfo::getNumberOfCores( cpu_id ) ) }, + { "CPU max frequency (MHz)", String( Devices::SystemInfo::getCPUMaxFrequency( cpu_id ) / 1e3 ) }, { "CPU cache sizes (L1d, L1i, L2, L3) (kiB)", cacheInfo }, #ifdef HAVE_CUDA { "GPU name", Devices::CudaDeviceInfo::getDeviceName( activeGPU ) }, diff --git a/src/Benchmarks/DistSpMV/tnl-benchmark-distributed-spmv.h b/src/Benchmarks/DistSpMV/tnl-benchmark-distributed-spmv.h index 11ae35b43..ecc001d66 100644 --- a/src/Benchmarks/DistSpMV/tnl-benchmark-distributed-spmv.h +++ b/src/Benchmarks/DistSpMV/tnl-benchmark-distributed-spmv.h @@ -177,11 +177,11 @@ struct SpmvBenchmark benchmark.setMetadataColumns( Benchmark::MetadataColumns({ // TODO: strip the device // {"matrix type", matrix.getType()}, - {"rows", matrix.getRows()}, - {"columns", matrix.getColumns()}, + {"rows", String( matrix.getRows() ) }, + {"columns", String( matrix.getColumns() ) }, // FIXME: getMaxRowLengths() returns 0 for matrices loaded from file // {"max elements per row", matrix.getMaxRowLength()}, - {"max elements per row", maxRowLength}, + {"max elements per row", String( maxRowLength ) }, } )); const bool reorder = parameters.getParameter< bool >( "reorder-dofs" ); diff --git a/src/Benchmarks/LinearSolvers/tnl-benchmark-linear-solvers.h b/src/Benchmarks/LinearSolvers/tnl-benchmark-linear-solvers.h index a898f156b..c31f776cd 100644 --- a/src/Benchmarks/LinearSolvers/tnl-benchmark-linear-solvers.h +++ b/src/Benchmarks/LinearSolvers/tnl-benchmark-linear-solvers.h @@ -347,11 +347,11 @@ struct LinearSolversBenchmark benchmark.setMetadataColumns( Benchmark::MetadataColumns({ // TODO: strip the device // {"matrix type", matrixPointer->getType()}, - {"rows", matrixPointer->getRows()}, - {"columns", matrixPointer->getColumns()}, + {"rows", String( matrixPointer->getRows() ) }, + {"columns", String( matrixPointer->getColumns() ) }, // FIXME: getMaxRowLengths() returns 0 for matrices loaded from file // {"max elements per row", matrixPointer->getMaxRowLength()}, - {"max elements per row", maxRowLength}, + {"max elements per row", String( maxRowLength ) }, } )); const bool reorder = parameters.getParameter< bool >( "reorder-dofs" ); -- GitLab From 7ecac318efce5afc4fabc22858f19c0feee89ce2 Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber Date: Fri, 14 Dec 2018 09:56:26 +0100 Subject: [PATCH 108/111] String constructor replaced with convertToString in tnl-benchmark-blas. --- src/Benchmarks/BLAS/tnl-benchmark-blas.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Benchmarks/BLAS/tnl-benchmark-blas.h b/src/Benchmarks/BLAS/tnl-benchmark-blas.h index 6419087a9..8c78205e7 100644 --- a/src/Benchmarks/BLAS/tnl-benchmark-blas.h +++ b/src/Benchmarks/BLAS/tnl-benchmark-blas.h @@ -43,7 +43,7 @@ runBlasBenchmarks( Benchmark & benchmark, metadata ); for( std::size_t size = minSize; size <= maxSize; size *= 2 ) { benchmark.setMetadataColumns( Benchmark::MetadataColumns({ - {"size", String( size ) }, + {"size", convertToString( size ) }, } )); benchmarkArrayOperations< Real >( benchmark, loops, size ); } @@ -53,7 +53,7 @@ runBlasBenchmarks( Benchmark & benchmark, metadata ); for( std::size_t size = minSize; size <= maxSize; size *= sizeStepFactor ) { benchmark.setMetadataColumns( Benchmark::MetadataColumns({ - { "size", String( size ) }, + { "size", convertToString( size ) }, } )); benchmarkVectorOperations< Real >( benchmark, loops, size ); } @@ -63,9 +63,9 @@ runBlasBenchmarks( Benchmark & benchmark, metadata ); for( std::size_t size = minSize; size <= maxSize; size *= 2 ) { benchmark.setMetadataColumns( Benchmark::MetadataColumns({ - {"rows", String( size ) }, - {"columns", String( size ) }, - {"elements per row", String( elementsPerRow ) }, + {"rows", convertToString( size ) }, + {"columns", convertToString( size ) }, + {"elements per row", convertToString( elementsPerRow ) }, } )); benchmarkSpmvSynthetic< Real >( benchmark, loops, size, elementsPerRow ); } -- GitLab From 66995c1c5265b138915c6c1cd9ab91866a0ba4c1 Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber Date: Fri, 14 Dec 2018 12:29:42 +0100 Subject: [PATCH 109/111] Added explicit conversions to String in Benchmark. --- src/Benchmarks/Benchmarks.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Benchmarks/Benchmarks.h b/src/Benchmarks/Benchmarks.h index de3727b21..ceb6b9c7e 100644 --- a/src/Benchmarks/Benchmarks.h +++ b/src/Benchmarks/Benchmarks.h @@ -504,9 +504,9 @@ Benchmark::MetadataMap getHardwareMetadata() { "system release", Devices::SystemInfo::getSystemRelease() }, { "start time", Devices::SystemInfo::getCurrentTime() }, #ifdef HAVE_MPI - { "number of MPI processes", (Communicators::MpiCommunicator::IsInitialized()) + { "number of MPI processes", String( (Communicators::MpiCommunicator::IsInitialized()) ? Communicators::MpiCommunicator::GetSize( Communicators::MpiCommunicator::AllGroup ) - : 1 }, + : 1 ) }, #endif { "OpenMP enabled", String( Devices::Host::isOMPEnabled() ) }, { "OpenMP threads", String( Devices::Host::getMaxThreadsCount() ) }, @@ -517,12 +517,12 @@ Benchmark::MetadataMap getHardwareMetadata() { "CPU cache sizes (L1d, L1i, L2, L3) (kiB)", cacheInfo }, #ifdef HAVE_CUDA { "GPU name", Devices::CudaDeviceInfo::getDeviceName( activeGPU ) }, - { "GPU architecture", deviceArch }, - { "GPU CUDA cores", Devices::CudaDeviceInfo::getCudaCores( activeGPU ) }, - { "GPU clock rate (MHz)", (double) Devices::CudaDeviceInfo::getClockRate( activeGPU ) / 1e3 }, - { "GPU global memory (GB)", (double) Devices::CudaDeviceInfo::getGlobalMemory( activeGPU ) / 1e9 }, - { "GPU memory clock rate (MHz)", (double) Devices::CudaDeviceInfo::getMemoryClockRate( activeGPU ) / 1e3 }, - { "GPU memory ECC enabled", Devices::CudaDeviceInfo::getECCEnabled( activeGPU ) }, + { "GPU architecture", String( deviceArch ) }, + { "GPU CUDA cores", String( Devices::CudaDeviceInfo::getCudaCores( activeGPU ) ) }, + { "GPU clock rate (MHz)", String( (double) Devices::CudaDeviceInfo::getClockRate( activeGPU ) / 1e3 ) }, + { "GPU global memory (GB)", String( (double) Devices::CudaDeviceInfo::getGlobalMemory( activeGPU ) / 1e9 ) }, + { "GPU memory clock rate (MHz)", String( (double) Devices::CudaDeviceInfo::getMemoryClockRate( activeGPU ) / 1e3 ) }, + { "GPU memory ECC enabled", String( Devices::CudaDeviceInfo::getECCEnabled( activeGPU ) ) }, #endif }; -- GitLab From 3ff23e25c458a3d335c2c2b154eb29b86fddb675 Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber Date: Fri, 14 Dec 2018 15:49:03 +0100 Subject: [PATCH 110/111] Fixed String::split method and added skipEmpty flag. --- src/TNL/String.cpp | 26 ++++++++++++++------------ src/TNL/String.h | 2 +- src/UnitTests/StringTest.cpp | 12 ++++++++++-- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/TNL/String.cpp b/src/TNL/String.cpp index 817c62cca..92663a4d8 100644 --- a/src/TNL/String.cpp +++ b/src/TNL/String.cpp @@ -335,22 +335,24 @@ String::strip( char strip ) const return ""; } -int String::split( Containers::List< String >& list, const char separator ) const +int String::split( Containers::List< String >& list, + const char separator, + bool skipEmpty ) const { list.reset(); - String copy( *this ); - int len = copy.getLength(); - for( int i = 0; i < len; i ++ ) - if( copy[ i ] == separator ) - copy[ i ] = 0; - for( int i = 0; i < len; i ++ ) + String s; + for( int i = 0; i < this->getLength(); i ++ ) { - if( copy[ i ] == 0 ) continue; - String new_string; - new_string.setString( ©.getString()[ i ] ); - i += new_string.getLength(); - list.Append( new_string ); + if( ( *this )[ i ] == separator ) + { + if( ! skipEmpty || s != "" ) + list.Append( s ); + s = ""; + } + else s += ( *this )[ i ]; } + if( ! skipEmpty || s != "" ) + list.Append( s ); return list.getSize(); } diff --git a/src/TNL/String.h b/src/TNL/String.h index a580cc4ae..44f42423f 100644 --- a/src/TNL/String.h +++ b/src/TNL/String.h @@ -253,7 +253,7 @@ class String /// @param list Name of list. /// @param separator Character, which separates substrings in given string. /// Empty character can not be used. - int split( Containers::List< String >& list, const char separator = ' ' ) const; + int split( Containers::List< String >& list, const char separator = ' ', bool skipEmpty = false ) const; ///// /// \brief Function for saving file. diff --git a/src/UnitTests/StringTest.cpp b/src/UnitTests/StringTest.cpp index 511bed7a8..f6ee1a572 100644 --- a/src/UnitTests/StringTest.cpp +++ b/src/UnitTests/StringTest.cpp @@ -295,6 +295,15 @@ TEST( StringTest, split ) EXPECT_EQ( list[ 2 ], "C" ); String( "abracadabra" ).split( list, 'a' ); + ASSERT_EQ( list.getSize(), 6 ); + EXPECT_EQ( list[ 0 ], "" ); + EXPECT_EQ( list[ 1 ], "br" ); + EXPECT_EQ( list[ 2 ], "c" ); + EXPECT_EQ( list[ 3 ], "d" ); + EXPECT_EQ( list[ 4 ], "br" ); + EXPECT_EQ( list[ 5 ], "" ); + + String( "abracadabra" ).split( list, 'a', true ); ASSERT_EQ( list.getSize(), 4 ); EXPECT_EQ( list[ 0 ], "br" ); EXPECT_EQ( list[ 1 ], "c" ); @@ -311,7 +320,6 @@ TEST( StringTest, split ) ASSERT_EQ( list.getSize(), 1 ); EXPECT_EQ( list[ 0 ], "abracadabra" ); - // !!!! ma problem s prazdnym stringom !!!! String( "a,,b,c" ).split( list, ',' ); ASSERT_EQ( list.getSize(), 4 ); EXPECT_EQ( list[ 0 ], "a" ); @@ -353,7 +361,6 @@ TEST( StringTest, getLine ) #endif - #include "GtestMissingError.h" int main( int argc, char* argv[] ) { @@ -364,3 +371,4 @@ int main( int argc, char* argv[] ) throw GtestMissingError(); #endif } + -- GitLab From 1a721bad83f485f7e856fc03281207a69e5adf91 Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber Date: Fri, 14 Dec 2018 15:55:33 +0100 Subject: [PATCH 111/111] Fixes after rebase. --- src/TNL/DistributedContainers/Subrange.h | 1 + src/TNL/Solvers/Linear/Preconditioners/Preconditioner.h | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/TNL/DistributedContainers/Subrange.h b/src/TNL/DistributedContainers/Subrange.h index e581c9a4f..1512bd2ee 100644 --- a/src/TNL/DistributedContainers/Subrange.h +++ b/src/TNL/DistributedContainers/Subrange.h @@ -13,6 +13,7 @@ #pragma once #include + #include #include #include diff --git a/src/TNL/Solvers/Linear/Preconditioners/Preconditioner.h b/src/TNL/Solvers/Linear/Preconditioners/Preconditioner.h index 58ab8c682..8d294bd8a 100644 --- a/src/TNL/Solvers/Linear/Preconditioners/Preconditioner.h +++ b/src/TNL/Solvers/Linear/Preconditioners/Preconditioner.h @@ -17,8 +17,6 @@ #include #include -#include "../Traits.h" - namespace TNL { namespace Solvers { namespace Linear { -- GitLab