diff --git a/Doxyfile b/Doxyfile index 59224c5..4b79341 100644 --- a/Doxyfile +++ b/Doxyfile @@ -1,7 +1,7 @@ -# Doxyfile 1.9.1 +# Doxyfile 1.18.0 # This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project. +# Doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. @@ -11,7 +11,17 @@ # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (\" \"). +# Values that contain spaces should be placed between quotes (" "). +# +# Note: +# +# Use Doxygen to compare the used configuration file with the template +# configuration file: +# doxygen -x [configFile] +# Use Doxygen to compare the used configuration file with the template +# configuration file without replacing the environment variables or CMake type +# replacement variables: +# doxygen -x_noenv [configFile] #--------------------------------------------------------------------------- # Project related configuration options @@ -41,7 +51,7 @@ PROJECT_NAME = "Intel xvec" PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer a +# for a project that appears at the top of each page and should give viewers a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = "Experimental C++ simd class library" @@ -53,24 +63,42 @@ PROJECT_BRIEF = "Experimental C++ simd class library" PROJECT_LOGO = +# With the PROJECT_ICON tag one can specify an icon that is included in the tabs +# when the HTML document is shown. Doxygen will copy the logo to the output +# directory. + +PROJECT_ICON = + # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is -# entered, it will be relative to the location where doxygen was started. If +# entered, it will be relative to the location where Doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = docs/doxygen -# 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 causes -# performance problems for the file system. +# If the CREATE_SUBDIRS tag is set to YES then Doxygen will create up to 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. Adjust CREATE_SUBDIRS_LEVEL to +# control the number of sub-directories. # The default value is: NO. CREATE_SUBDIRS = NO -# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# Controls the number of sub-directories that will be created when +# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every +# level increment doubles the number of directories, resulting in 4096 +# directories at level 8 which is the default and also the maximum value. The +# sub-directories are organized in 2 levels, the first level always has a fixed +# number of 16 directories. +# Minimum value: 0, maximum value: 8, default value: 8. +# This tag requires that the tag CREATE_SUBDIRS is set to YES. + +CREATE_SUBDIRS_LEVEL = 8 + +# If the ALLOW_UNICODE_NAMES tag is set to YES, Doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. @@ -79,36 +107,28 @@ CREATE_SUBDIRS = NO ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this +# documentation generated by Doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. -# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, -# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), -# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, -# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, -# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, -# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, -# Ukrainian and Vietnamese. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian, +# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English +# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek, +# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with +# English messages), Korean, Korean-en (Korean with English messages), Latvian, +# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, +# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, +# Swedish, Turkish, Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English -# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all generated output in the proper direction. -# Possible values are: None, LTR, RTL and Context. -# The default value is: None. - -OUTPUT_TEXT_DIRECTION = None - -# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# If the BRIEF_MEMBER_DESC tag is set to YES, 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. # The default value is: YES. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# If the REPEAT_BRIEF tag is set to YES, 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 @@ -139,13 +159,13 @@ ABBREVIATE_BRIEF = "The $name class" \ the # 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 +# Doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# 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. @@ -153,7 +173,7 @@ ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO -# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# If the FULL_PATH_NAMES tag is set to YES, 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 # The default value is: YES. @@ -163,11 +183,11 @@ FULL_PATH_NAMES = YES # 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 +# If left blank the directory from which Doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which -# will be relative from the directory where doxygen is started. +# will be relative from the directory where Doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = @@ -181,41 +201,42 @@ STRIP_FROM_PATH = 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 +# If the SHORT_NAMES tag is set to YES, Doxygen will generate much shorter (but +# less readable) file names. This can be useful if your file system doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. 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-style will behave just like regular Qt- -# style comments (thus requiring an explicit @brief command for a brief -# description.) +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen will interpret the +# first line (until the first dot, question mark or exclamation mark) of a +# Javadoc-style comment as the brief description. If set to NO, the Javadoc- +# style will behave just like regular Qt-style comments (thus requiring an +# explicit @brief command for a brief description.) # The default value is: NO. JAVADOC_AUTOBRIEF = NO -# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# If the JAVADOC_BANNER tag is set to YES then Doxygen will interpret a line # such as # /*************** # as being the beginning of a Javadoc-style comment "banner". If set to NO, the # Javadoc-style will behave just like regular comments and it will not be -# interpreted by doxygen. +# interpreted by Doxygen. # The default value is: NO. JAVADOC_BANNER = 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 Qt-style will behave just like regular Qt-style comments (thus -# requiring an explicit \brief command for a brief description.) +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will interpret the first +# line (until the first dot, question mark or exclamation mark) of a Qt-style +# comment as the brief description. If set to NO, the Qt-style will behave just +# like regular Qt-style comments (thus requiring an explicit \brief command for +# a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# 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 behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this @@ -227,10 +248,10 @@ QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO -# By default Python docstrings are displayed as preformatted text and doxygen's +# By default Python docstrings are displayed as preformatted text and Doxygen's # special commands cannot be used. By setting PYTHON_DOCSTRING to NO the -# doxygen's special commands can be used and the contents of the docstring -# documentation blocks is shown as doxygen documentation. +# Doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as Doxygen documentation. # The default value is: YES. PYTHON_DOCSTRING = YES @@ -241,7 +262,7 @@ PYTHON_DOCSTRING = YES INHERIT_DOCS = YES -# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# 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. # The default value is: NO. @@ -258,16 +279,16 @@ TAB_SIZE = 4 # the documentation. An alias has the form: # name=value # For example adding -# "sideeffect=@par Side Effects:\n" +# "sideeffect=@par Side Effects:^^" # 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 (in the resulting output). You can put ^^ in the value part of an -# alias to insert a newline as if a physical newline was in the original file. -# When you need a literal { or } or , in the value part of an alias you have to -# escape them by means of a backslash (\), this can lead to conflicts with the -# commands \{ and \} for these it is advised to use the version @{ and @} or use -# a double escape (\\{ and \\}) +# "Side Effects:". Note that you cannot put \n's in the value part of an alias +# to insert newlines (in the resulting output). You can put ^^ in the value part +# of an alias to insert a newline as if a physical newline was in the original +# file. When you need a literal { or } or , in the value part of an alias you +# have to escape them by means of a backslash (\), this can lead to conflicts +# with the commands \{ and \} for these it is advised to use the version @{ and +# @} or use a double escape (\\{ and \\}) ALIASES = @@ -311,58 +332,92 @@ OPTIMIZE_OUTPUT_SLICE = NO # 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, -# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, -# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# language is one of the parsers supported by Doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, +# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser # tries to guess whether the code is fixed or free formatted code, this is the -# default for Fortran type files). For instance to make doxygen treat .inc files +# default for Fortran type files). 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: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by doxygen. When specifying no_extension you should add +# the files are not read by Doxygen. When specifying no_extension you should add # * to the FILE_PATTERNS. # # Note see also the list of default file extension mappings. EXTENSION_MAPPING = .no_extension=c++ -# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# If the MARKDOWN_SUPPORT tag is enabled then Doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See https://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you can -# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# The output of markdown processing is further processed by Doxygen, so you can +# mix Doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES +# If the MARKDOWN_STRICT tag is enabled then Doxygen treats text in comments as +# Markdown formatted also in cases where Doxygen's native markup format +# conflicts with that of Markdown. This is only relevant in cases where +# backticks are used. Doxygen's native markup style allows a single quote to end +# a text fragment started with a backtick and then treat it as a piece of quoted +# text, whereas in Markdown such text fragment is treated as verbatim and only +# ends when a second matching backtick is found. Also, Doxygen's native markup +# format requires double quotes to be escaped when they appear in a backtick +# section, whereas this is not needed for Markdown. +# The default value is: YES. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +MARKDOWN_STRICT = YES + # When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up # to that level are automatically included in the table of contents, even if # they do not have an id attribute. # Note: This feature currently applies only to Markdown headings. -# Minimum value: 0, maximum value: 99, default value: 5. +# Minimum value: 0, maximum value: 99, default value: 6. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. TOC_INCLUDE_HEADINGS = 5 -# When enabled doxygen tries to link words that correspond to documented +# The MARKDOWN_ID_STYLE tag can be used to specify the algorithm used to +# generate identifiers for the Markdown headings. Note: Every identifier is +# unique. +# Possible values are: DOXYGEN use a fixed 'autotoc_md' string followed by a +# sequence number starting at 0 and GITHUB use the lower case version of title +# with any whitespace replaced by '-' and punctuation characters removed. +# The default value is: DOXYGEN. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +MARKDOWN_ID_STYLE = DOXYGEN + +# When enabled Doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or -# globally by setting AUTOLINK_SUPPORT to NO. +# globally by setting AUTOLINK_SUPPORT to NO. Words listed in the +# AUTOLINK_IGNORE_WORDS tag are excluded from automatic linking. # The default value is: YES. AUTOLINK_SUPPORT = YES +# This tag specifies a list of words that, when matching the start of a word in +# the documentation, will suppress auto links generation, if it is enabled via +# AUTOLINK_SUPPORT. This list does not affect links explicitly created using # +# or the \link or \ref commands. +# This tag requires that the tag AUTOLINK_SUPPORT is set to YES. + +AUTOLINK_IGNORE_WORDS = + # 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 +# tag to YES in order to let Doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); -# versus func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. +# versus func(std::string) {}). This also makes the inheritance and +# collaboration diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO @@ -374,16 +429,16 @@ BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# https://www.riverbankcomputing.com/software/sip/intro) 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. +# https://www.riverbankcomputing.com/software) 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. # The default value is: NO. 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 will make -# doxygen to replace the get and set methods by a property in the documentation. +# 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. @@ -392,7 +447,7 @@ SIP_SUPPORT = 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 +# 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. # The default value is: NO. @@ -450,34 +505,42 @@ TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the -# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small -# doxygen will become slower. If the cache is too large, memory is wasted. The +# code, Doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# Doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 -# symbols. At the end of a run doxygen will report the cache usage and suggest +# symbols. At the end of a run Doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 -# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use -# during processing. When set to 0 doxygen will based this on the number of +# The NUM_PROC_THREADS specifies the number of threads Doxygen is allowed to use +# during processing. When set to 0 Doxygen will based this on the number of # cores available in the system. You can set it explicitly to a value larger # than 0 to get more control over the balance between CPU load and processing # speed. At this moment only the input processing can be done using multiple # threads. Since this is still an experimental feature the default is set to 1, -# which efficively disables parallel processing. Please report any issues you +# which effectively disables parallel processing. Please report any issues you # encounter. Generating dot graphs in parallel is controlled by the # DOT_NUM_THREADS setting. -# Minimum value: 0, maximum value: 32, default value: 1. +# Minimum value: 0, maximum value: 512, default value: 1. NUM_PROC_THREADS = 1 +# If the TIMESTAMP tag is set different from NO then each generated page will +# contain the date or date and time when the page was generated. Setting this to +# NO can help when comparing the output of multiple runs. +# Possible values are: YES, NO, DATETIME and DATE. +# The default value is: NO. + +TIMESTAMP = NO + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- -# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# 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 respectively EXTRACT_STATIC tags are set to YES. @@ -543,7 +606,7 @@ EXTRACT_ANON_NSPACES = NO RESOLVE_UNNAMED_PARAMS = YES -# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members inside documented classes or files. If set to NO 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. @@ -551,22 +614,31 @@ RESOLVE_UNNAMED_PARAMS = YES HIDE_UNDOC_MEMBERS = NO -# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# 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, these classes will be included in the various overviews. This option -# has no effect if EXTRACT_ALL is enabled. +# will also hide undocumented C++ concepts if enabled. This option has no effect +# if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# If the HIDE_UNDOC_NAMESPACES tag is set to YES, Doxygen will hide all +# undocumented namespaces that are normally visible in the namespace hierarchy. +# If set to NO, these namespaces will be included in the various overviews. This +# option has no effect if EXTRACT_ALL is enabled. +# The default value is: YES. + +HIDE_UNDOC_NAMESPACES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all friend # declarations. If set to NO, these declarations will be included in the # documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO -# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# 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, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. @@ -580,37 +652,44 @@ HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO -# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# With the correct setting of option CASE_SENSE_NAMES Doxygen will better be # able to match the capabilities of the underlying filesystem. In case the # filesystem is case sensitive (i.e. it supports files in the same directory # whose names only differ in casing), the option must be set to YES to properly # deal with such files in case they appear in the input. For filesystems that -# are not case sensitive the option should be be set to NO to properly deal with +# are not case sensitive the option should be set to NO to properly deal with # output files written for symbols that only differ in casing, such as for two # classes, one named CLASS and the other named Class, and to also support # references to files without having to specify the exact matching casing. On -# Windows (including Cygwin) and MacOS, users should typically set this option +# Windows (including Cygwin) and macOS, users should typically set this option # to NO, whereas on Linux or other Unix flavors it should typically be set to # YES. -# The default value is: system dependent. +# Possible values are: SYSTEM, NO and YES. +# The default value is: SYSTEM. CASE_SENSE_NAMES = YES -# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# If the HIDE_SCOPE_NAMES tag is set to NO then Doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO -# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then Doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. HIDE_COMPOUND_REFERENCE= NO -# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class +# will show which file needs to be included to use the class. +# The default value is: YES. + +SHOW_HEADERFILE = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES then Doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. @@ -623,7 +702,7 @@ SHOW_INCLUDE_FILES = YES SHOW_GROUPED_MEMB_INC = NO -# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. @@ -635,14 +714,14 @@ FORCE_LOCAL_INCLUDES = NO INLINE_INFO = YES -# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# If the SORT_MEMBER_DOCS tag is set to YES 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. # The default value is: YES. SORT_MEMBER_DOCS = YES -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# If the SORT_BRIEF_DOCS tag is set to YES then Doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. @@ -650,7 +729,7 @@ SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# 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 constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. @@ -662,7 +741,7 @@ SORT_BRIEF_DOCS = NO SORT_MEMBERS_CTORS_1ST = NO -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# 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 group names will # appear in their defined order. # The default value is: NO. @@ -679,11 +758,11 @@ SORT_GROUP_NAMES = NO SORT_BY_SCOPE_NAME = NO -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# If the STRICT_PROTO_MATCHING option is enabled and Doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a -# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# simple string match. By disabling STRICT_PROTO_MATCHING Doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. @@ -714,6 +793,27 @@ GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES +# The GENERATE_REQUIREMENTS tag can be used to enable (YES) or disable (NO) the +# requirements page. When enabled, this page is automatically created when at +# least one comment block with a \requirement command appears in the input. +# The default value is: YES. + +GENERATE_REQUIREMENTS = YES + +# The REQ_TRACEABILITY_INFO tag controls if traceability information is shown on +# the requirements page (only relevant when using \requirement comment blocks). +# The setting NO will disable the traceability information altogether. The +# setting UNSATISFIED_ONLY will show a list of requirements that are missing a +# satisfies relation (through the command: \satisfies). Similarly the setting +# UNVERIFIED_ONLY will show a list of requirements that are missing a verifies +# relation (through the command: \verifies). Setting the tag to YES (the +# default) will show both lists if applicable. +# Possible values are: YES, NO, UNSATISFIED_ONLY and UNVERIFIED_ONLY. +# The default value is: YES. +# This tag requires that the tag GENERATE_REQUIREMENTS is set to YES. + +REQ_TRACEABILITY_INFO = YES + # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. @@ -753,24 +853,25 @@ SHOW_FILES = 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 +# 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 command input-file, where command is the value of the -# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided -# by doxygen. Whatever the program writes to standard output is used as the file +# popen()) the command command input_file, where command is the value of the +# FILE_VERSION_FILTER tag, and input_file is the name of an input file provided +# by Doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. 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 +# by Doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. You can +# 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. +# will be used as the name of the layout file. See also section "Changing the +# layout of pages" for information. # -# Note that if you run doxygen from a directory containing a file called -# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# Note that if you run Doxygen from a directory containing a file called +# DoxygenLayout.xml, Doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = @@ -785,19 +886,35 @@ LAYOUT_FILE = CITE_BIB_FILES = +# The EXTERNAL_TOOL_PATH tag can be used to extend the search path (PATH +# environment variable) so that external tools such as latex and gs can be +# found. +# Note: Directories specified with EXTERNAL_TOOL_PATH are added in front of the +# path already specified by the PATH variable, and are added in the order +# specified. +# Note: This option is particularly useful for macOS version 14 (Sonoma) and +# higher, when running Doxygen from Doxywizard, because in this case any user- +# defined changes to the PATH are ignored. A typical example on macOS is to set +# EXTERNAL_TOOL_PATH = /Library/TeX/texbin /usr/local/bin +# together with the standard path, the full search path used by doxygen when +# launching external tools will then become +# PATH=/Library/TeX/texbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin + +EXTERNAL_TOOL_PATH = + #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to -# standard output by doxygen. If QUIET is set to YES this implies that the +# standard output by Doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are -# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# generated to standard error (stderr) by Doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. @@ -805,52 +922,97 @@ QUIET = NO WARNINGS = YES -# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# If the WARN_IF_UNDOCUMENTED tag 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. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES -# If the WARN_IF_DOC_ERROR tag 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. +# If the WARN_IF_DOC_ERROR tag is set to YES, Doxygen will generate warnings for +# potential errors in the documentation, such as documenting some parameters in +# a documented function twice, or documenting parameters that don't exist or +# using markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES +# If WARN_IF_INCOMPLETE_DOC is set to YES, Doxygen will warn about incomplete +# function parameter documentation. If set to NO, Doxygen will accept that some +# parameters have no documentation without warning. +# The default value is: YES. + +WARN_IF_INCOMPLETE_DOC = YES + # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return -# value. If set to NO, doxygen will only warn about wrong or incomplete -# parameter documentation, but not about the absence of documentation. If -# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# value. If set to NO, Doxygen will only warn about wrong parameter +# documentation, but not about the absence of documentation. If EXTRACT_ALL is +# set to YES then this flag will automatically be disabled. See also +# WARN_IF_INCOMPLETE_DOC # The default value is: NO. WARN_NO_PARAMDOC = NO -# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, Doxygen will warn about +# undocumented enumeration values. If set to NO, Doxygen will accept +# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: NO. + +WARN_IF_UNDOC_ENUM_VAL = NO + +# If WARN_LAYOUT_FILE option is set to YES, Doxygen will warn about issues found +# while parsing the user defined layout file, such as missing or wrong elements. +# See also LAYOUT_FILE for details. If set to NO, problems with the layout file +# will be suppressed. +# The default value is: YES. + +WARN_LAYOUT_FILE = YES + +# If the WARN_AS_ERROR tag is set to YES then Doxygen will immediately stop when # a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS -# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but -# at the end of the doxygen process doxygen will return with a non-zero status. -# Possible values are: NO, YES and FAIL_ON_WARNINGS. +# then Doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the Doxygen process Doxygen will return with a non-zero status. +# If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS_PRINT then Doxygen behaves +# like FAIL_ON_WARNINGS but in case no WARN_LOGFILE is defined Doxygen will not +# write the warning messages in between other messages but write them at the end +# of a run, in case a WARN_LOGFILE is defined the warning messages will be +# besides being in the defined file also be shown at the end of a run, unless +# the WARN_LOGFILE is defined as - i.e. standard output (stdout) in that case +# the behavior will remain as with the setting FAIL_ON_WARNINGS. +# Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT. # The default value is: NO. WARN_AS_ERROR = NO -# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# 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) +# See also: WARN_LINE_FORMAT # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" +# In the $text part of the WARN_FORMAT command it is possible that a reference +# to a more specific place is given. To make it easier to jump to this place +# (outside of Doxygen) the user can define a custom "cut" / "paste" string. +# Example: +# WARN_LINE_FORMAT = "'vi $file +$line'" +# See also: WARN_FORMAT +# The default value is: at line $line of file $file. + +WARN_LINE_FORMAT = "at line $line of file $file" + # 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 standard -# error (stderr). +# error (stderr). In case the file specified cannot be opened for writing the +# warning and error messages are written to standard error. When as file - is +# specified the warning and error messages are written to standard output +# (stdout). WARN_LOGFILE = @@ -868,31 +1030,42 @@ INPUT = include/xvec \ include/xvec/simd # This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# that Doxygen parses. Internally Doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: # https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# See also: INPUT_FILE_ENCODING # The default value is: UTF-8. INPUT_ENCODING = UTF-8 +# This tag can be used to specify the character encoding of the source files +# that Doxygen parses. The INPUT_FILE_ENCODING tag can be used to specify +# character encoding on a per file pattern basis. Doxygen will compare the file +# name with each pattern and apply the encoding instead of the default +# INPUT_ENCODING if there is a match. The character encodings are a list of the +# form: pattern=encoding (like *.php=ISO-8859-1). +# See also: INPUT_ENCODING for further information on supported encodings. + +INPUT_FILE_ENCODING = + # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not -# read by doxygen. +# read by Doxygen. # # Note the list of default checked file patterns might differ from the list of # default file extension mappings. # -# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, -# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, -# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, -# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), -# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl, -# *.ucf, *.qsf and *.ice. +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cxxm, +# *.cpp, *.cppm, *.ccm, *.c++, *.c++m, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, +# *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, +# *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be +# provided as Doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. FILE_PATTERNS = *.hpp @@ -906,7 +1079,7 @@ RECURSIVE = NO # 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. # -# Note that relative paths are relative to the directory from which doxygen is +# Note that relative paths are relative to the directory from which Doxygen is # run. EXCLUDE = @@ -931,10 +1104,7 @@ EXCLUDE_PATTERNS = # (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 -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories use the pattern */test/* +# ANamespace::AClass, ANamespace::*Test EXCLUDE_SYMBOLS = @@ -964,7 +1134,7 @@ EXAMPLE_RECURSIVE = NO IMAGE_PATH = -# The INPUT_FILTER tag can be used to specify a program that doxygen should +# 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: # @@ -979,9 +1149,14 @@ IMAGE_PATH = # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # +# Note that Doxygen will use the data processed and written to standard output +# for further processing, therefore nothing else, like debug statements or used +# commands (so in case of a Windows batch file always use @echo OFF), should be +# written to standard output. +# # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. +# properly processed by Doxygen. INPUT_FILTER = @@ -994,7 +1169,7 @@ INPUT_FILTER = # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. +# properly processed by Doxygen. FILTER_PATTERNS = @@ -1016,10 +1191,28 @@ FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub -# and want to reuse the introduction page also for the doxygen output. +# and want to reuse the introduction page also for the Doxygen output. USE_MDFILE_AS_MAINPAGE = +# If the IMPLICIT_DIR_DOCS tag is set to YES, any README.md file found in sub- +# directories of the project's root, is used as the documentation for that sub- +# directory, except when the README.md starts with a \dir, \page or \mainpage +# command. If set to NO, the README.md file needs to start with an explicit \dir +# command in order to be used as directory documentation. +# The default value is: YES. + +IMPLICIT_DIR_DOCS = YES + +# The Fortran standard specifies that for fixed formatted Fortran code all +# characters from position 72 are to be considered as comment. A common +# extension is to allow longer lines before the automatic comment starts. The +# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can +# be processed before the automatic comment starts. +# Minimum value: 7, maximum value: 10000, default value: 72. + +FORTRAN_COMMENT_AFTER = 72 + #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- @@ -1034,12 +1227,13 @@ USE_MDFILE_AS_MAINPAGE = SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, -# classes and enums directly into the documentation. +# multi-line macros, enums or list initialized variables directly into the +# documentation. # The default value is: NO. INLINE_SOURCES = NO -# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct Doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. @@ -1077,7 +1271,7 @@ REFERENCES_LINK_SOURCE = YES SOURCE_TOOLTIPS = 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 +# 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 https://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. @@ -1091,14 +1285,14 @@ SOURCE_TOOLTIPS = YES # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # -# The result: instead of the source browser generated by doxygen, the links to +# The result: instead of the source browser generated by Doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO -# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# If the VERBATIM_HEADERS tag is set the YES 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. # See also: Section \class. @@ -1106,26 +1300,28 @@ USE_HTAGS = NO VERBATIM_HEADERS = YES -# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# If the CLANG_ASSISTED_PARSING tag is set to YES then Doxygen will use the # clang parser (see: # http://clang.llvm.org/) for more accurate parsing at the cost of reduced # performance. This can be particularly helpful with template rich C++ code for -# which doxygen's built-in parser lacks the necessary type information. -# Note: The availability of this option depends on whether or not doxygen was +# which Doxygen's built-in parser lacks the necessary type information. +# Note: The availability of this option depends on whether or not Doxygen was # generated with the -Duse_libclang=ON option for CMake. # The default value is: NO. CLANG_ASSISTED_PARSING = NO -# If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to -# YES then doxygen will add the directory of each input to the include path. +# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS +# tag is set to YES then Doxygen will add the directory of each input to the +# include path. # The default value is: YES. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. CLANG_ADD_INC_PATHS = YES # If clang assisted parsing is enabled you can provide the compiler with command # line options that you would normally use when invoking the compiler. Note that -# the include paths will already be set by doxygen for the files and directories +# the include paths will already be set by Doxygen for the files and directories # specified with INPUT and INCLUDE_PATH. # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. @@ -1139,7 +1335,7 @@ CLANG_OPTIONS = # specifying the -p option to a clang tool, such as clang-check. These options # will then be passed to the parser. Any options specified with CLANG_OPTIONS # will be added as well. -# Note: The availability of this option depends on whether or not doxygen was +# Note: The availability of this option depends on whether or not Doxygen was # generated with the -Duse_libclang=ON option for CMake. CLANG_DATABASE_PATH = @@ -1155,10 +1351,11 @@ CLANG_DATABASE_PATH = ALPHABETICAL_INDEX = YES -# 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 a prefix (or a list of prefixes) that should be ignored -# while generating the index headers. +# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes) +# that should be ignored while generating the index headers. The IGNORE_PREFIX +# tag works for classes, function and member names. The entity will be placed in +# the alphabetical list under the first letter of the entity name that remains +# after removing the prefix. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = @@ -1167,7 +1364,7 @@ IGNORE_PREFIX = # Configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# If the GENERATE_HTML tag is set to YES, Doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES @@ -1188,40 +1385,40 @@ HTML_OUTPUT = html HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for -# each generated HTML page. If the tag is left blank doxygen will generate a +# each generated HTML page. If the tag is left blank Doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets -# that doxygen needs, which is dependent on the configuration options used (e.g. +# that Doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" -# for information on how to generate the default header that doxygen normally +# for information on how to generate the default header that Doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the -# default header when upgrading to a newer version of doxygen. For a description +# default header when upgrading to a newer version of Doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each -# generated HTML page. If the tag is left blank doxygen will generate a standard +# generated HTML page. If the tag is left blank Doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer -# that doxygen normally uses. +# that Doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. 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 left blank doxygen will generate a default style sheet. +# the HTML output. If left blank Doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style -# sheet that doxygen normally uses. +# sheet that Doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. @@ -1231,13 +1428,18 @@ HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets -# created by doxygen. Using this option one can overrule certain style aspects. +# created by Doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the -# list). For an example see the documentation. +# list). +# Note: Since the styling of scrollbars can currently not be overruled in +# Webkit/Chromium, the styling will be left out of the default doxygen.css if +# one or more extra stylesheets have been specified. So if scrollbar +# customization is desired it has to be added explicitly. For an example see the +# documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = @@ -1252,9 +1454,22 @@ HTML_EXTRA_STYLESHEET = HTML_EXTRA_FILES = +# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output +# should be rendered with a dark or light theme. +# Possible values are: LIGHT always generates light mode output, DARK always +# generates dark mode output, AUTO_LIGHT automatically sets the mode according +# to the user preference, uses light mode if no preference is set (the default), +# AUTO_DARK automatically sets the mode according to the user preference, uses +# dark mode if no preference is set and TOGGLE allows a user to switch between +# light and dark mode via a button. +# The default value is: AUTO_LIGHT. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE = AUTO_LIGHT + # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to -# this color. Hue is specified as an angle on a colorwheel, see +# this color. Hue is specified as an angle on a color-wheel, see # https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. @@ -1264,7 +1479,7 @@ HTML_EXTRA_FILES = HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors -# in the HTML output. For a value of 0 the output will use grayscales only. A +# in the HTML output. For a value of 0 the output will use gray-scales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1282,15 +1497,6 @@ HTML_COLORSTYLE_SAT = 100 HTML_COLORSTYLE_GAMMA = 80 -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting this -# to YES can help to show when doxygen was last run and thus if the -# documentation is up to date. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_TIMESTAMP = NO - # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # documentation will contain a main index with vertical navigation menus that # are dynamically created via JavaScript. If disabled, the navigation index will @@ -1310,6 +1516,33 @@ HTML_DYNAMIC_MENUS = YES HTML_DYNAMIC_SECTIONS = NO +# If the HTML_CODE_FOLDING tag is set to YES then classes and functions can be +# dynamically folded and expanded in the generated HTML source code. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_CODE_FOLDING = YES + +# If the HTML_COPY_CLIPBOARD tag is set to YES then Doxygen will show an icon in +# the top right corner of code and text fragments that allows the user to copy +# its content to the clipboard. Note this only works if supported by the browser +# and the web page is served via a secure context (see: +# https://www.w3.org/TR/secure-contexts/), i.e. using the https: or file: +# protocol. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COPY_CLIPBOARD = YES + +# Doxygen stores a couple of settings persistently in the browser (via e.g. +# cookies). By default these settings apply to all HTML pages generated by +# Doxygen across all projects. The HTML_PROJECT_COOKIE tag can be used to store +# the settings under a project specific key, such that the user preferences will +# be stored separately. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_PROJECT_COOKIE = + # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to @@ -1327,7 +1560,7 @@ HTML_INDEX_NUM_ENTRIES = 100 # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: # https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To -# create a documentation set, doxygen will generate a Makefile in the HTML +# 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 @@ -1346,6 +1579,13 @@ GENERATE_DOCSET = NO DOCSET_FEEDNAME = "Doxygen generated docs" +# This tag determines the URL of the docset 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. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDURL = + # 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. @@ -1368,14 +1608,18 @@ DOCSET_PUBLISHER_ID = org.doxygen.Publisher DOCSET_PUBLISHER_NAME = Publisher -# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# If the GENERATE_HTMLHELP tag is set to YES then Doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: -# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows. +# on Windows. In the beginning of 2021 Microsoft took the original page, with +# a.o. the download links, offline (the HTML help workshop was already many +# years in maintenance mode). You can download the HTML help workshop from the +# web archives at Installation executable (see: +# http://web.archive.org/web/20160201063255/https://download.microsoft.com/downl +# oad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). # # The HTML Help Workshop contains a compiler that can convert all HTML output -# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# generated by Doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for @@ -1395,7 +1639,7 @@ CHM_FILE = # 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. +# Doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. @@ -1429,6 +1673,16 @@ BINARY_TOC = NO TOC_EXPAND = NO +# The SITEMAP_URL tag is used to specify the full URL of the place where the +# generated documentation will be placed on the server by the user during the +# deployment of the documentation. The generated sitemap is called sitemap.xml +# and placed on the directory specified by HTML_OUTPUT. In case no SITEMAP_URL +# is specified no sitemap is generated. For information about the sitemap +# protocol see https://www.sitemaps.org +# This tag requires that the tag GENERATE_HTML is set to YES. + +SITEMAP_URL = + # 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 @@ -1487,7 +1741,7 @@ QHP_CUST_FILTER_ATTRS = QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location (absolute path -# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# including file name) of Qt's qhelpgenerator. If non-empty Doxygen will try to # run qhelpgenerator on the generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1531,18 +1785,39 @@ DISABLE_INDEX = NO # 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. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can -# further fine-tune the look of the index. As an example, the default style -# sheet generated by doxygen has an example that shows how to put an image at -# the root of the tree instead of the PROJECT_NAME. Since the tree basically has -# the same information as the tab index, you could consider setting -# DISABLE_INDEX to YES when enabling this option. -# The default value is: NO. +# further fine tune the look of the index (see "Fine-tuning the output"). As an +# example, the default style sheet generated by Doxygen has an example that +# shows how to put an image at the root of the tree instead of the PROJECT_NAME. +# Since the tree basically has more details information than the tab index, you +# could consider setting DISABLE_INDEX to YES when enabling this option. +# The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO +# When GENERATE_TREEVIEW is set to YES, the PAGE_OUTLINE_PANEL option determines +# if an additional navigation panel is shown at the right hand side of the +# screen, displaying an outline of the contents of the main page, similar to +# e.g. https://developer.android.com/reference If GENERATE_TREEVIEW is set to +# NO, this option has no effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +PAGE_OUTLINE_PANEL = YES + +# When GENERATE_TREEVIEW is set to YES, the FULL_SIDEBAR option determines if +# the side bar is limited to only the treeview area (value NO) or if it should +# extend to the full height of the window (value YES). Setting this to YES gives +# a layout similar to e.g. https://docs.readthedocs.io with more room for +# contents, but less room for the project logo, title, and description. If +# GENERATE_TREEVIEW is set to NO, this option has no effect. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FULL_SIDEBAR = NO + # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that -# doxygen will group on one line in the generated HTML documentation. +# Doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. @@ -1551,6 +1826,12 @@ GENERATE_TREEVIEW = NO ENUM_VALUES_PER_LINE = 4 +# When the SHOW_ENUM_VALUES tag is set doxygen will show the specified +# enumeration values besides the enumeration mnemonics. +# The default value is: NO. + +SHOW_ENUM_VALUES = 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. # Minimum value: 0, maximum value: 1500, default value: 250. @@ -1558,14 +1839,21 @@ ENUM_VALUES_PER_LINE = 4 TREEVIEW_WIDTH = 250 -# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# If the EXT_LINKS_IN_WINDOW option is set to YES, Doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO -# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg +# If the OBFUSCATE_EMAILS tag is set to YES, Doxygen will obfuscate email +# addresses. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +OBFUSCATE_EMAILS = YES + +# If the HTML_FORMULA_FORMAT option is set to svg, Doxygen will use the pdf2svg # tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see # https://inkscape.org) to generate formulas as SVG images instead of PNGs for # the HTML output. These images will generally look nicer at scaled resolutions. @@ -1578,24 +1866,13 @@ HTML_FORMULA_FORMAT = png # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful -# doxygen run you need to manually remove any form_*.png images from the HTML +# Doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 -# Use the FORMULA_TRANSPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are not -# supported properly for IE 6.0, but are supported on all modern browsers. -# -# Note that when changing this option you need to delete any form_*.png files in -# the HTML output directory before the changes have effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_TRANSPARENT = YES - # The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands # to create new LaTeX commands to be used in formulas as building blocks. See # the section "Including formulas" for details. @@ -1613,51 +1890,90 @@ FORMULA_MACROFILE = USE_MATHJAX = NO +# With MATHJAX_VERSION it is possible to specify the MathJax version to be used. +# Note that the different versions of MathJax have different requirements with +# regards to the different settings, so it is possible that also other MathJax +# settings have to be changed when switching between the different MathJax +# versions. +# Possible values are: MathJax_2, MathJax_3 and MathJax_4. +# The default value is: MathJax_2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_VERSION = MathJax_2 + # When MathJax is enabled you can set the default output format to be used for -# the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. +# the MathJax output. For more details about the output format see MathJax +# version 2 (see: +# https://docs.mathjax.org/en/v2.7/output.html), MathJax version 3 (see: +# https://docs.mathjax.org/en/v3.2/output/index.html) and MathJax version 4 +# (see: +# https://docs.mathjax.org/en/v4.0/output/index.htm). # Possible values are: HTML-CSS (which is slower, but has the best -# compatibility), NativeMML (i.e. MathML) and SVG. +# compatibility. This is the name for Mathjax version 2, for MathJax version 3 +# this will be translated into chtml), NativeMML (i.e. MathML. Only supported +# for MathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This +# is the name for Mathjax version 3, for MathJax version 2 this will be +# translated into HTML-CSS) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML -# output directory using the MATHJAX_RELPATH option. The destination directory -# should contain the MathJax.js script. For instance, if the mathjax directory -# is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax -# Content Delivery Network so you can quickly see the result without installing -# MathJax. However, it is strongly recommended to install a local copy of -# MathJax from https://www.mathjax.org before deployment. -# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2. +# output directory using the MATHJAX_RELPATH option. For Mathjax version 2 the +# destination directory should contain the MathJax.js script. For instance, if +# the mathjax directory is located at the same level as the HTML output +# directory, then MATHJAX_RELPATH should be ../mathjax. For Mathjax versions 3 +# and 4 the destination directory should contain the tex-.js script +# (where is either chtml or svg). The default value points to the +# MathJax Content Delivery Network so you can quickly see the result without +# installing MathJax. However, it is strongly recommended to install a local +# copy of MathJax from https://www.mathjax.org before deployment. The default +# value is: +# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2 +# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3 +# - in case of MathJax version 4: https://cdn.jsdelivr.net/npm/mathjax@4 # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/ # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example +# for MathJax version 2 (see https://docs.mathjax.org/en/v2.7/tex.html): # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# For example for MathJax version 3 (see +# https://docs.mathjax.org/en/v3.2/input/tex/extensions/): +# MATHJAX_EXTENSIONS = ams +# For example for MathJax version 4 (see +# https://docs.mathjax.org/en/v4.0/input/tex/extensions/): +# MATHJAX_EXTENSIONS = units +# Note that for Mathjax version 4 quite a few extensions are already +# automatically loaded. To disable a package in Mathjax version 4 one can use +# the package name prepended with a minus sign (- like MATHJAX_EXTENSIONS += +# -textmacros) # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = -# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces -# of code that will be used on startup of the MathJax code. See the MathJax site -# (see: -# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an -# example see the documentation. +# The MATHJAX_CODEFILE tag can be used to specify a file with JavaScript pieces +# of code that will be used on startup of the MathJax code. See the Mathjax site +# for more details: +# - MathJax version 2 (see: +# https://docs.mathjax.org/en/v2.7/) +# - MathJax version 3 (see: +# https://docs.mathjax.org/en/v3.2/) +# - MathJax version 4 (see: +# https://docs.mathjax.org/en/v4.0/) For an example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = -# When the SEARCHENGINE tag is enabled doxygen will generate a search box for -# the HTML output. The underlying search engine uses javascript and DHTML and +# When the SEARCHENGINE tag is enabled 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), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. -# For large projects the javascript based search engine can be slow, then +# For large projects the JavaScript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically @@ -1676,7 +1992,7 @@ SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a web server instead of a web client using JavaScript. There # are two flavors of web server based searching depending on the EXTERNAL_SEARCH -# setting. When disabled, doxygen will generate a PHP script for searching and +# setting. When disabled, Doxygen will generate a PHP script for searching and # an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing # and searching needs to be provided by external tools. See the section # "External Indexing and Searching" for details. @@ -1685,7 +2001,7 @@ SEARCHENGINE = YES SERVER_BASED_SEARCH = NO -# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP +# When EXTERNAL_SEARCH tag is enabled Doxygen will no longer generate the PHP # script for searching. Instead the search results are written to an XML file # which needs to be processed by an external indexer. Doxygen will invoke an # external search engine pointed to by the SEARCHENGINE_URL option to obtain the @@ -1730,7 +2046,7 @@ SEARCHDATA_FILE = searchdata.xml EXTERNAL_SEARCH_ID = -# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through Doxygen # projects other than the one defined by this configuration file, but that are # all added to the same external search index. Each project needs to have a # unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of @@ -1744,7 +2060,7 @@ EXTRA_SEARCH_MAPPINGS = # Configuration options related to the LaTeX output #--------------------------------------------------------------------------- -# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output. +# If the GENERATE_LATEX tag is set to YES, Doxygen will generate LaTeX output. # The default value is: YES. GENERATE_LATEX = NO @@ -1789,7 +2105,7 @@ MAKEINDEX_CMD_NAME = makeindex LATEX_MAKEINDEX_CMD = makeindex -# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX +# 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. # The default value is: NO. @@ -1818,36 +2134,37 @@ PAPER_TYPE = a4 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. See -# section "Doxygen usage" for information on how to let doxygen write the -# default header to a separate file. +# The LATEX_HEADER tag can be used to specify a user-defined 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. It +# is highly recommended to start with a default header using +# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty +# and then modify the file new_header.tex. See also section "Doxygen usage" for +# information on how to generate the default header that Doxygen normally uses. # -# Note: Only use a user-defined header if you know what you are doing! The -# following commands have a special meaning inside the header: $title, -# $datetime, $date, $doxygenversion, $projectname, $projectnumber, -# $projectbrief, $projectlogo. Doxygen will replace $title with the empty -# string, for the replacement values of the other commands the user is referred -# to HTML_HEADER. +# Note: Only use a user-defined header if you know what you are doing! +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of Doxygen. For a description +# of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_HEADER = -# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the -# generated LaTeX document. The footer should contain everything after the last -# chapter. If it is left blank doxygen will generate a standard footer. See +# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for +# the generated LaTeX document. The footer should contain everything after the +# last chapter. If it is left blank Doxygen will generate a standard footer. See # LATEX_HEADER for more information on how to generate a default footer and what -# special commands can be used inside the footer. -# -# Note: Only use a user-defined footer if you know what you are doing! +# special commands can be used inside the footer. See also section "Doxygen +# usage" for information on how to generate the default footer that Doxygen +# normally uses. Note: Only use a user-defined footer if you know what you are +# doing! # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_FOOTER = # The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined # LaTeX style sheets that are included after the standard style sheets created -# by doxygen. Using this option one can overrule certain style aspects. Doxygen +# by Doxygen. Using this option one can overrule certain style aspects. Doxygen # will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the @@ -1873,7 +2190,7 @@ LATEX_EXTRA_FILES = PDF_HYPERLINKS = YES -# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as +# If the USE_PDFLATEX tag is set to YES, Doxygen will use the engine as # specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX # files. Set this option to YES, to get a higher quality PDF documentation. # @@ -1883,48 +2200,36 @@ PDF_HYPERLINKS = YES 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. +# The LATEX_BATCHMODE tag signals the behavior of LaTeX in case of an error. +# Possible values are: NO same as ERROR_STOP, YES same as BATCH, BATCH In batch +# mode nothing is printed on the terminal, errors are scrolled as if is +# hit at every error; missing files that TeX tries to input or request from +# keyboard input (\read on a not open input stream) cause the job to abort, +# NON_STOP In nonstop mode the diagnostic message will appear on the terminal, +# but there is no possibility of user interaction just like in batch mode, +# SCROLL In scroll mode, TeX will stop only for missing files to input or if +# keyboard input is necessary and ERROR_STOP In errorstop mode, TeX will stop at +# each error, asking for user intervention. # The default value is: NO. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_BATCHMODE = NO -# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the +# If the LATEX_HIDE_INDICES tag is set to YES then Doxygen will not include the # index chapters (such as File Index, Compound Index, etc.) in the output. # The default value is: NO. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_HIDE_INDICES = NO -# If the LATEX_SOURCE_CODE tag 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. -# The default value is: NO. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_SOURCE_CODE = NO - # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. See # https://en.wikipedia.org/wiki/BibTeX and \cite for more info. -# The default value is: plain. +# The default value is: plainnat. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_BIB_STYLE = plain -# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated -# page will contain the date and time when the page was generated. Setting this -# to NO can help when comparing the output of multiple runs. -# The default value is: NO. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_TIMESTAMP = NO - # The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) # path from which the emoji images will be read. If a relative path is entered, # it will be relative to the LATEX_OUTPUT directory. If left blank the @@ -1937,7 +2242,7 @@ LATEX_EMOJI_DIRECTORY = # Configuration options related to the RTF output #--------------------------------------------------------------------------- -# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The +# 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 too pretty with other RTF # readers/editors. # The default value is: NO. @@ -1952,7 +2257,7 @@ GENERATE_RTF = NO RTF_OUTPUT = rtf -# If the COMPACT_RTF tag is set to YES, doxygen generates more compact 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. # The default value is: NO. @@ -1972,38 +2277,36 @@ COMPACT_RTF = NO RTF_HYPERLINKS = NO -# Load stylesheet definitions from file. Syntax is similar to doxygen's +# Load stylesheet definitions from file. Syntax is similar to Doxygen's # configuration file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. # # See also section "Doxygen usage" for information on how to generate the -# default style sheet that doxygen normally uses. +# default style sheet that Doxygen normally uses. # This tag requires that the tag GENERATE_RTF is set to YES. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an RTF document. Syntax is -# similar to doxygen's configuration file. A template extensions file can be +# similar to Doxygen's configuration file. A template extensions file can be # generated using doxygen -e rtf extensionFile. # This tag requires that the tag GENERATE_RTF is set to YES. RTF_EXTENSIONS_FILE = -# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code -# with syntax highlighting in the RTF output. -# -# Note that which sources are shown also depends on other settings such as -# SOURCE_BROWSER. -# The default value is: NO. +# The RTF_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the RTF_OUTPUT output directory. +# Note that the files will be copied as-is; there are no commands or markers +# available. # This tag requires that the tag GENERATE_RTF is set to YES. -RTF_SOURCE_CODE = NO +RTF_EXTRA_FILES = #--------------------------------------------------------------------------- # Configuration options related to the man page output #--------------------------------------------------------------------------- -# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for +# If the GENERATE_MAN tag is set to YES, Doxygen will generate man pages for # classes and files. # The default value is: NO. @@ -2034,7 +2337,7 @@ MAN_EXTENSION = .3 MAN_SUBDIR = -# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it +# 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. @@ -2047,7 +2350,7 @@ 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 +# 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. # The default value is: NO. @@ -2061,7 +2364,7 @@ GENERATE_XML = NO XML_OUTPUT = xml -# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program +# 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. @@ -2070,7 +2373,7 @@ XML_OUTPUT = xml XML_PROGRAMLISTING = YES -# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include +# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, Doxygen will include # namespace members in file scope as well, matching the HTML output. # The default value is: NO. # This tag requires that the tag GENERATE_XML is set to YES. @@ -2081,7 +2384,7 @@ XML_NS_MEMB_FILE_SCOPE = NO # Configuration options related to the DOCBOOK output #--------------------------------------------------------------------------- -# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files +# If the GENERATE_DOCBOOK tag is set to YES, Doxygen will generate Docbook files # that can be used to generate PDF. # The default value is: NO. @@ -2095,32 +2398,49 @@ GENERATE_DOCBOOK = NO DOCBOOK_OUTPUT = docbook -# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the -# program listings (including syntax highlighting and cross-referencing -# information) to the DOCBOOK output. Note that enabling this will significantly -# increase the size of the DOCBOOK output. -# The default value is: NO. -# This tag requires that the tag GENERATE_DOCBOOK is set to YES. - -DOCBOOK_PROGRAMLISTING = NO - #--------------------------------------------------------------------------- # Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- -# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an -# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures +# If the GENERATE_AUTOGEN_DEF tag is set to YES, Doxygen will generate an +# AutoGen Definitions (see https://autogen.sourceforge.net/) file that captures # the structure of the code including all documentation. Note that this feature # is still experimental and incomplete at the moment. # The default value is: NO. GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# Configuration options related to Sqlite3 output +#--------------------------------------------------------------------------- + +# If the GENERATE_SQLITE3 tag is set to YES Doxygen will generate a Sqlite3 +# database with symbols found by Doxygen stored in tables. +# The default value is: NO. + +GENERATE_SQLITE3 = NO + +# The SQLITE3_OUTPUT tag is used to specify where the Sqlite3 database will be +# put. If a relative path is entered the value of OUTPUT_DIRECTORY will be put +# in front of it. +# The default directory is: sqlite3. +# This tag requires that the tag GENERATE_SQLITE3 is set to YES. + +SQLITE3_OUTPUT = sqlite3 + +# The SQLITE3_RECREATE_DB tag is set to YES, the existing doxygen_sqlite3.db +# database file will be recreated with each Doxygen run. If set to NO, Doxygen +# will warn if a database file is already found and not modify it. +# The default value is: YES. +# This tag requires that the tag GENERATE_SQLITE3 is set to YES. + +SQLITE3_RECREATE_DB = YES + #--------------------------------------------------------------------------- # Configuration options related to the Perl module output #--------------------------------------------------------------------------- -# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module +# 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. @@ -2128,7 +2448,7 @@ GENERATE_AUTOGEN_DEF = NO GENERATE_PERLMOD = NO -# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary +# 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. # The default value is: NO. @@ -2158,13 +2478,13 @@ PERLMOD_MAKEVAR_PREFIX = # Configuration options related to the preprocessor #--------------------------------------------------------------------------- -# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all +# If the ENABLE_PREPROCESSING tag is set to YES, Doxygen will evaluate all # C-preprocessor directives found in the sources and include files. # The default value is: YES. ENABLE_PREPROCESSING = YES -# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names +# If the MACRO_EXPANSION tag is set to YES, Doxygen will expand all macro names # in the source code. If set to NO, only conditional compilation will be # performed. Macro expansion can be done in a controlled way by setting # EXPAND_ONLY_PREDEF to YES. @@ -2190,7 +2510,8 @@ 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. +# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of +# RECURSIVE has no effect here. # This tag requires that the tag SEARCH_INCLUDES is set to YES. INCLUDE_PATH = include @@ -2222,7 +2543,7 @@ PREDEFINED = EXPAND_AS_DEFINED = _XVEC_NAMESPACE -# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will +# If the SKIP_FUNCTION_MACROS tag is set to YES then Doxygen's preprocessor will # remove all references to 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 @@ -2246,26 +2567,26 @@ SKIP_FUNCTION_MACROS = YES # section "Linking to external documentation" for more information about the use # of tag files. # Note: 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 +# 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 +# When a file name is specified after GENERATE_TAGFILE, Doxygen will create a # tag file that is based on the input files it reads. See section "Linking to # external documentation" for more information about the usage of tag files. GENERATE_TAGFILE = -# If the ALLEXTERNALS tag is set to YES, all external class will be listed in -# the class index. If set to NO, only the inherited external classes will be -# listed. +# If the ALLEXTERNALS tag is set to YES, all external classes and namespaces +# will be listed in the class and namespace index. If set to NO, only the +# inherited external classes will be listed. # The default value is: NO. 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 +# in the topic index. If set to NO, only the current project's groups will be # listed. # The default value is: YES. @@ -2279,99 +2600,124 @@ EXTERNAL_GROUPS = YES EXTERNAL_PAGES = YES #--------------------------------------------------------------------------- -# Configuration options related to the dot tool +# Configuration options related to diagram generator tools #--------------------------------------------------------------------------- -# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram -# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to -# NO turns the diagrams off. Note that this option also works with HAVE_DOT -# disabled, but it is recommended to install and use dot, since it yields more -# powerful graphs. -# The default value is: YES. - -CLASS_DIAGRAMS = YES - -# You can include diagrams made with dia in doxygen documentation. Doxygen will -# then run dia to produce the diagram and insert it in the documentation. The -# DIA_PATH tag allows you to specify the directory where the dia binary resides. -# If left empty dia is assumed to be found in the default search path. - -DIA_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. # The default value is: YES. HIDE_UNDOC_RELATIONS = YES -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# 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 (see: -# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent +# https://www.graphviz.org/), 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 value is: YES. +# The default value is: NO. HAVE_DOT = NO -# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed -# to run in parallel. When set to 0 doxygen will base this on the number of +# The DOT_NUM_THREADS specifies the number of dot invocations Doxygen is allowed +# to run in parallel. When set to 0 Doxygen will base this on the number of # processors available in the system. You can set it explicitly to a value # larger than 0 to get control over the balance between CPU load and processing # speed. -# Minimum value: 0, maximum value: 32, default value: 0. +# Minimum value: 0, maximum value: 512, default value: 0. # This tag requires that the tag HAVE_DOT is set to YES. DOT_NUM_THREADS = 0 -# When you want a differently looking font in the dot files that doxygen -# generates you can specify the font name using DOT_FONTNAME. You 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. -# The default value is: Helvetica. +# The DOT_BATCH_SIZE specifies the number of dot graphs Doxygen is allowed to +# compile in a single invocation of dot. When set to 1 Doxygen will invoke dot +# for each graph separately, which can cause significant process creation +# overhead especially on systems with many CPU cores. Together with +# DOT_NUM_THREADS this setting can be used to optimise the dot processing speed +# for a particular system. Doxygen will try to give each thread a balanced batch +# of work. If the total number of graphs to process exceeds DOT_NUM_THREADS * +# DOT_BATCH_SIZE then additional batches will be created for dot to process. +# Minimum value: 1, maximum value: 1000, default value: 50. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_FONTNAME = Helvetica +DOT_BATCH_SIZE = 50 + +# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of +# subgraphs. When you want a differently looking font in the dot files that +# Doxygen generates you can specify fontname, fontcolor and fontsize attributes. +# For details please see Node, +# Edge and Graph Attributes specification You 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. Default graphviz fontsize is 14. +# The default value is: fontname=Helvetica,fontsize=10. +# This tag requires that the tag HAVE_DOT is set to YES. -# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of -# dot graphs. -# Minimum value: 4, maximum value: 24, default value: 10. +DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10" + +# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can +# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. Complete documentation about +# arrows shapes. +# The default value is: labelfontname=Helvetica,labelfontsize=10. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10" + +# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes +# around nodes set 'shape=plain' or 'shape=plaintext' Shapes specification +# The default value is: shape=box,height=0.2,width=0.4. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_FONTSIZE = 10 +DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4" -# By default doxygen will tell dot to use the default font as specified with -# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set -# the path where dot can find it using this tag. +# You can set the path where dot can find font specified with fontname in +# DOT_COMMON_ATTR and others dot attributes. # This tag requires that the tag HAVE_DOT is set to YES. DOT_FONTPATH = -# If the CLASS_GRAPH tag is 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 CLASS_DIAGRAMS tag to NO. +# If the CLASS_GRAPH tag is set to YES or GRAPH or BUILTIN then Doxygen will +# generate a graph for each documented class showing the direct and indirect +# inheritance relations. In case the CLASS_GRAPH tag is set to YES or GRAPH and +# HAVE_DOT is enabled as well, then dot will be used to draw the graph. In case +# the CLASS_GRAPH tag is set to YES and HAVE_DOT is disabled or if the +# CLASS_GRAPH tag is set to BUILTIN, then the built-in generator will be used. +# If the CLASS_GRAPH tag is set to TEXT the direct and indirect inheritance +# relations will be shown as texts / links. Explicit enabling an inheritance +# graph or choosing a different representation for an inheritance graph of a +# specific class, can be accomplished by means of the command \inheritancegraph. +# Disabling an inheritance graph can be accomplished by means of the command +# \hideinheritancegraph. +# Possible values are: NO, YES, TEXT, GRAPH and BUILTIN. # The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. CLASS_GRAPH = NO -# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a +# If the COLLABORATION_GRAPH tag is 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. +# class with other documented classes. Explicit enabling a collaboration graph, +# when COLLABORATION_GRAPH is set to NO, can be accomplished by means of the +# command \collaborationgraph. Disabling a collaboration graph can be +# accomplished by means of the command \hidecollaborationgraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. COLLABORATION_GRAPH = NO -# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for -# groups, showing the direct groups dependencies. +# If the GROUP_GRAPHS tag is set to YES then Doxygen will generate a graph for +# groups, showing the direct groups dependencies. Explicit enabling a group +# dependency graph, when GROUP_GRAPHS is set to NO, can be accomplished by means +# of the command \groupgraph. Disabling a directory graph can be accomplished by +# means of the command \hidegroupgraph. See also the chapter Grouping in the +# manual. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. GROUP_GRAPHS = NO -# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and +# 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. # The default value is: NO. @@ -2392,10 +2738,19 @@ UML_LOOK = NO UML_LIMIT_NUM_FIELDS = 10 -# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and +# If the UML_LOOK tag is enabled, field labels are shown along the edge between +# two class nodes. If there are many fields and many nodes the graph may become +# too cluttered. The UML_MAX_EDGE_LABELS threshold limits the number of items to +# make the size more manageable. Set this to 0 for no limit. +# Minimum value: 0, maximum value: 100, default value: 10. +# This tag requires that the tag UML_LOOK is set to YES. + +UML_MAX_EDGE_LABELS = 10 + +# If the DOT_UML_DETAILS tag is set to NO, Doxygen will show attributes and # methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS -# tag is set to YES, doxygen will add type and arguments for attributes and -# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen +# tag is set to YES, Doxygen will add type and arguments for attributes and +# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, Doxygen # will not generate fields with class member information in the UML graphs. The # class diagrams will look similar to the default class diagrams but using UML # notation for the relationships. @@ -2407,8 +2762,8 @@ DOT_UML_DETAILS = NO # The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters # to display on a single line. If the actual line length exceeds this threshold -# significantly it will wrapped across multiple lines. Some heuristics are apply -# to avoid ugly line breaks. +# significantly it will be wrapped across multiple lines. Some heuristics are +# applied to avoid ugly line breaks. # Minimum value: 0, maximum value: 1000, default value: 17. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2423,24 +2778,29 @@ DOT_WRAP_THRESHOLD = 17 TEMPLATE_RELATIONS = NO # If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to -# YES then doxygen will generate a graph for each documented file showing the +# 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. +# files. Explicit enabling an include graph, when INCLUDE_GRAPH is is set to NO, +# can be accomplished by means of the command \includegraph. Disabling an +# include graph can be accomplished by means of the command \hideincludegraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. INCLUDE_GRAPH = NO # If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are -# set to YES then doxygen will generate a graph for each documented file showing +# 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. +# files. Explicit enabling an included by graph, when INCLUDED_BY_GRAPH is set +# to NO, can be accomplished by means of the command \includedbygraph. Disabling +# an included by graph can be accomplished by means of the command +# \hideincludedbygraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. INCLUDED_BY_GRAPH = YES -# If the CALL_GRAPH tag is set to YES then doxygen will generate a call +# If the CALL_GRAPH tag is 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. @@ -2452,7 +2812,7 @@ INCLUDED_BY_GRAPH = YES CALL_GRAPH = NO -# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller +# If the CALLER_GRAPH tag is 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. @@ -2464,46 +2824,59 @@ CALL_GRAPH = NO CALLER_GRAPH = NO -# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical +# If the GRAPHICAL_HIERARCHY tag is set to YES then Doxygen will graphical # hierarchy of all classes instead of a textual one. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. GRAPHICAL_HIERARCHY = NO -# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the +# If the DIRECTORY_GRAPH tag is 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. +# files in the directories. Explicit enabling a directory graph, when +# DIRECTORY_GRAPH is set to NO, can be accomplished by means of the command +# \directorygraph. Disabling a directory graph can be accomplished by means of +# the command \hidedirectorygraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. DIRECTORY_GRAPH = NO +# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels +# of child directories generated in directory dependency graphs by dot. +# Minimum value: 1, maximum value: 25, default value: 1. +# This tag requires that the tag DIRECTORY_GRAPH is set to YES. + +DIR_GRAPH_MAX_DEPTH = 1 + # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. For an explanation of the image formats see the section # output formats in the documentation of the dot tool (Graphviz (see: -# http://www.graphviz.org/)). -# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order -# to make the SVG files visible in IE 9+ (other browsers do not have this -# requirement). -# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd, -# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo, -# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo, -# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and -# png:gdiplus:gdiplus. +# https://www.graphviz.org/)). +# +# Note the formats svg:cairo and svg:cairo:cairo cannot be used in combination +# with INTERACTIVE_SVG (the INTERACTIVE_SVG will be set to NO). +# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo, +# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus, +# png:gdiplus:gdiplus, svg:cairo, svg:cairo:cairo, svg:svg, svg:svg:core, +# gif:cairo, gif:cairo:gd, gif:cairo:gdiplus, gif:gdiplus, gif:gdiplus:gdiplus, +# gif:gd, gif:gd:gd, jpg:cairo, jpg:cairo:gd, jpg:cairo:gdiplus, jpg:gd, +# jpg:gd:gd, jpg:gdiplus and jpg:gdiplus:gdiplus. # The default value is: png. # This tag requires that the tag HAVE_DOT is set to YES. DOT_IMAGE_FORMAT = png -# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to -# enable generation of interactive SVG images that allow zooming and panning. +# If DOT_IMAGE_FORMAT is set to svg or svg:svg or svg:svg:core, then this option +# can be set to YES to enable generation of interactive SVG images that allow +# zooming and panning. # # Note that this requires a modern browser other than Internet Explorer. Tested # and working are Firefox, Chrome, Safari, and Opera. -# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make -# the SVG files visible. Older versions of IE do not have SVG support. +# +# Note This option will be automatically disabled when DOT_IMAGE_FORMAT is set +# to svg:cairo or svg:cairo:cairo. # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2522,11 +2895,12 @@ DOT_PATH = DOTFILE_DIRS = -# The MSCFILE_DIRS tag can be used to specify one or more directories that -# contain msc files that are included in the documentation (see the \mscfile -# command). +# You can include diagrams made with dia in Doxygen documentation. Doxygen will +# then run dia to produce the diagram and insert it in the documentation. The +# DIA_PATH tag allows you to specify the directory where the dia binary resides. +# If left empty dia is assumed to be found in the default search path. -MSCFILE_DIRS = +DIA_PATH = # The DIAFILE_DIRS tag can be used to specify one or more directories that # contain dia files that are included in the documentation (see the \diafile @@ -2534,28 +2908,86 @@ MSCFILE_DIRS = DIAFILE_DIRS = -# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the -# path where java can find the plantuml.jar file. If left blank, it is assumed -# PlantUML is not used or called during a preprocessing step. Doxygen will -# generate a warning when it encounters a \startuml command in this case and -# will not generate output for the diagram. +# When using PlantUML, the PLANTUML_JAR_PATH tag should be used to specify the +# path where java can find the plantuml.jar file or to the filename of jar file +# to be used. If left blank, it is assumed PlantUML is not used or called during +# a preprocessing step. Doxygen will generate a warning when it encounters a +# \startuml command in this case and will not generate output for the diagram. PLANTUML_JAR_PATH = -# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a -# configuration file for plantuml. +# When using PlantUML, the PLANTUML_CFG_FILE tag can be used to specify a +# configuration file for PlantUML. PLANTUML_CFG_FILE = -# When using plantuml, the specified paths are searched for files specified by -# the !include statement in a plantuml block. +# When using PlantUML, the specified paths are searched for files specified by +# the !include statement in a PlantUML block. PLANTUML_INCLUDE_PATH = +# The PLANTUMLFILE_DIRS tag can be used to specify one or more directories that +# contain PlantUml files that are included in the documentation (see the +# \plantumlfile command). + +PLANTUMLFILE_DIRS = + +# When using Mermaid diagrams with CLI rendering, the MERMAID_PATH tag should be +# used to specify the directory where the mmdc (Mermaid CLI) executable can be +# found. If left blank, CLI-based rendering is disabled. For HTML output, +# client-side rendering via JavaScript is used by default and does not require +# mmdc. For LaTeX/PDF output, mmdc is required to pre-generate images. Doxygen +# will generate a warning when CLI rendering is needed but mmdc is not +# available. + +MERMAID_PATH = + +# When using Mermaid diagrams, the MERMAID_CONFIG_FILE tag can be used to +# specify a JSON configuration file for the Mermaid CLI tool (mmdc). This file +# can contain theme settings and other Mermaid configuration options. + +MERMAID_CONFIG_FILE = + +# The MERMAID_RENDER_MODE tag selects how Mermaid diagrams are rendered. +# Possible values are: AUTO (use client-side rendering for HTML and mmdc for +# LaTeX/PDF and other formats. If MERMAID_PATH is not set, non-HTML diagrams +# will produce a warning), CLI (use the mmdc tool to pre-generate images +# (requires Node.js and mermaid-js/mermaid-cli). Works for all output formats) +# and CLIENT_SIDE (embed mermaid.js in HTML output for client-side rendering. +# Does not require mmdc but only works for HTML output). +# The default value is: AUTO. + +MERMAID_RENDER_MODE = AUTO + +# The MERMAID_JS_URL tag specifies the URL to load mermaid.js from when using +# client-side rendering (MERMAID_RENDER_MODE is CLIENT_SIDE or AUTO). The +# default points to the latest Mermaid v11 release on the jsDelivr CDN. +# +# The default CDN URL requires internet access when viewing the generated +# documentation. For offline use, download mermaid.esm.min.mjs and set this to a +# relative path, or use MERMAID_RENDER_MODE=CLI to pre-generate images instead. +# Examples: +# - Latest v11 (default): +# https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs +# - Pinned version: +# https://cdn.jsdelivr.net/npm/mermaid@11.3.0/dist/mermaid.esm.min.mjs +# - Local copy: ./mermaid.esm.min.mjs (user must place file in HTML output +# directory) +# The default value is: +# https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs. + +MERMAID_JS_URL = https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs + +# The MERMAIDFILE_DIRS tag can be used to specify one or more directories that +# contain Mermaid files that are included in the documentation (see the +# \mermaidfile command). + +MERMAIDFILE_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 +# larger than this value, Doxygen will truncate the graph, which is visualized +# by representing a node as a red box. Note that 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. @@ -2576,40 +3008,37 @@ DOT_GRAPH_MAX_NODES = 50 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). -# The default value is: NO. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES to 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. -# The default value is: NO. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_MULTI_TARGETS = NO - -# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page +# If the GENERATE_LEGEND tag is set to YES Doxygen will generate a legend page # explaining the meaning of the various boxes and arrows in the dot generated # graphs. +# Note: This tag requires that UML_LOOK isn't set, i.e. the Doxygen internal +# graphical representation for inheritance and collaboration diagrams is used. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. GENERATE_LEGEND = YES -# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate +# If the DOT_CLEANUP tag is set to YES, Doxygen will remove the intermediate # files that are used to generate the various graphs. # -# Note: This setting is not only used for dot files but also for msc and -# plantuml temporary files. +# Note: This setting is not only used for dot files but also for msc temporary +# files. # The default value is: YES. DOT_CLEANUP = YES + +# You can define message sequence charts within Doxygen comments using the \msc +# command. If the MSCGEN_TOOL tag is left empty (the default), then Doxygen will +# use a built-in version of mscgen tool to produce the charts. Alternatively, +# the MSCGEN_TOOL tag can also specify the name an external tool. For instance, +# specifying prog as the value, Doxygen will call the tool as prog -T +# -o . The external tool should support +# output file formats "png", "eps", "svg", and "ismap". + +MSCGEN_TOOL = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the \mscfile +# command). + +MSCFILE_DIRS = diff --git a/include/xvec/detail/core.hpp b/include/xvec/detail/core.hpp index 7bc09f6..1e92489 100644 --- a/include/xvec/detail/core.hpp +++ b/include/xvec/detail/core.hpp @@ -191,6 +191,7 @@ concept builtin_vectorizable = || (complex_number<_Tp> && simple_vectorizable); /// Trait-based form of vectorization concept. +/// \ingroup cpp29_p2964 template inline constexpr bool disable_vectorization = std::is_pointer_v<_Tp> || @@ -327,7 +328,6 @@ concept generator_invocable = for (bool check : checks) if (!check) return false; return true; }(std::make_integer_sequence{}); -///@} template concept mask_operator = any_same_v concept math_floating_point = vec_floating_point struct rebind {}; template struct rebind<_Tp, basic_vec<_Sp, _Abi>> { @@ -362,12 +370,23 @@ template struct resize<_Np, }; template using resize_t = typename resize<_Np, _Vp>::type; -/// Shortened aliases for common types. +/// @} cpp26_traits + +/// Shortened alias for a vector type. +/// @ingroup cpp26_overview template::size()> using vec = basic_vec<_Tp, simd_fixed_size_abi<_Np>>; + +/// Shortened alias for a mask type. +/// @ingroup cpp26_mask_overview template::size()> using mask = basic_mask>; -///@{ -/// flags for controlling the behaviour of simd operations like conversions and memory accesses. +/** + * @defgroup cpp26_flags C++26: Load and store flags + * @brief Flags controlling element conversion and memory alignment. + * + * @see https://eel.is/c++draft/simd.flags + * @{ + */ template struct flags { template @@ -377,6 +396,8 @@ template struct flags { } }; +/// @} cpp26_flags + namespace detail { class flag_convert {}; class flag_aligned {}; @@ -384,24 +405,28 @@ namespace detail { class flag_unchecked {}; // Add extra flags to the existing flags. - ///@{ constexpr auto add_unchecked_flag(auto f) { return f | flags{}; }; constexpr auto add_convert_flag(auto f) { return f | flags{}; }; - ///@} /// @brief Query whether the given flags contains the specified type. template constexpr bool contains_flag(flags<_Flags...>) { return (std::is_same_v<_F, _Flags> || ...); } } +/// @addtogroup cpp26_flags +/// @{ + /// Standard flags. -///@{ inline constexpr flags<> flag_default{}; inline constexpr flags flag_convert{}; inline constexpr flags flag_aligned{}; template requires (std::has_single_bit(_N)) inline constexpr flags> flag_overaligned{}; -///@} + +/// @} cpp26_flags + +/// @addtogroup cpp29_p2964 +/// @{ /// Conversion flag, used to pass destination type to a simd_convert customisation point. template @@ -412,10 +437,13 @@ struct convert_to_t { template inline constexpr convert_to_t<_Tp> convert_to{}; +/// @} cpp29_p2964 + namespace detail { /// Traits for standard builtin vector types. +/// @internal template struct vec_traits { @@ -490,6 +518,7 @@ struct vec_traits }; /// Traits for generic mask types which use a standard vector register to represent the mask. +/// @internal template struct mask_traits { diff --git a/include/xvec/detail/invoke.hpp b/include/xvec/detail/invoke.hpp index bfefde1..c7dda90 100644 --- a/include/xvec/detail/invoke.hpp +++ b/include/xvec/detail/invoke.hpp @@ -35,6 +35,28 @@ inline constexpr bool are_all_sizes_equal = (... && (Size == Sizes)); } // End namespace detail +/** + * @defgroup cpp29_p2929 Chunked invocation + * @brief Invoke a callable on corresponding chunks of vectors or masks. + * + * Proposed in P2929, "chunked_invoke", previously named simd_invoke. + * + * @see https://wg21.link/P2929 + * @{ + */ + +/// @brief Invoke a callable on corresponding vector or mask chunks. +/// @tparam _SuggestedN Chunk size, or zero to deduce a common native width. +/// @tparam _Fn The callable type. +/// @tparam _Arg0 The first vector or mask argument type. +/// @tparam _Args The remaining vector or mask argument types. +/// @param fn The callable invoked on each set of corresponding chunks. +/// @param arg0 The first vector or mask argument. +/// @param args The remaining vector or mask arguments. +/// @return Concatenated vector or mask results, or void for a void-returning callable. +/// @details All arguments must have equal element counts. The final chunk may +/// be smaller than the selected chunk size. The callable may accept a trailing +/// argument giving the beginning index of the chunk. template constexpr auto chunked_invoke(_Fn fn, const _Arg0& arg0, const _Args&... args) { @@ -93,4 +115,6 @@ constexpr auto chunked_invoke(_Fn fn, const _Arg0& arg0, const _Args&... args) } +/// @} cpp29_p2929 + } // namespace _XVEC_NAMESPACE::simd diff --git a/include/xvec/detail/iterator.hpp b/include/xvec/detail/iterator.hpp index 59a7698..b23174d 100644 --- a/include/xvec/detail/iterator.hpp +++ b/include/xvec/detail/iterator.hpp @@ -17,15 +17,27 @@ namespace _XVEC_NAMESPACE::simd { +/** + * @defgroup cpp26_iterator C++26: SIMD iteration + * @brief Random-access iteration over vector and mask elements. + * + * @see https://eel.is/c++draft/simd.iterator + * @{ + */ + +/// @brief xvec implementation of the exposition-only SIMD iterator. +/// @tparam _Simd The vector or mask type being traversed. template class simd_iterator { public: /// The simd object over which iteration is happening. + /// @internal _Simd* data = nullptr; /// The current position of the iterator within the simd being iterated. + /// @internal simd_size_type index = 0; // Traits @@ -34,22 +46,34 @@ class simd_iterator using iterator_concept = std::random_access_iterator_tag; using difference_type = simd_size_type; + /// Default-construct an iterator. constexpr simd_iterator() = default; + + /// Copy an iterator. constexpr simd_iterator(const simd_iterator&) = default; + + /// Construct an iterator at element x of s. constexpr simd_iterator(_Simd& s, simd_size_type x) : data(std::addressof(s)), index(x) {} + /// Copy-assign an iterator. constexpr simd_iterator& operator=(const simd_iterator&) = default; + /// Convert a mutable iterator to a const iterator. constexpr simd_iterator(const simd_iterator>& i) requires std::is_const_v<_Simd> : data(i.data), index(i.index) {} - // Dereference the iterator to get the simd element. + /// Return the current element. constexpr value_type operator*() const { return (*data)[index]; } + /// Return the element at the specified relative offset. constexpr value_type operator[](difference_type i) const { return (*data)[index + i]; } + /// Advance to the next element. constexpr simd_iterator& operator++() { index += 1; return *this; } + + /// Move to the previous element. constexpr simd_iterator& operator--() { index -= 1; return *this; } + /// Advance to the next element, returning the original iterator. constexpr simd_iterator operator++(int) { simd_iterator i = *this; @@ -57,6 +81,7 @@ class simd_iterator return i; } + /// Move to the previous element, returning the original iterator. constexpr simd_iterator operator--(int) { @@ -65,24 +90,42 @@ class simd_iterator return i; } + /// Return the distance from another iterator. constexpr difference_type operator-(simd_iterator rhs) const { return index - rhs.index; } + /// Return an iterator advanced by the specified offset. friend constexpr simd_iterator operator+(difference_type x, const simd_iterator& it) { return simd_iterator(*it.data, it.index + x); } + + /// Return an iterator advanced by the specified offset. friend constexpr simd_iterator operator+(const simd_iterator& it, difference_type x) { return simd_iterator(*it.data, it.index + x); } + + /// Return an iterator moved backward by the specified offset. friend constexpr simd_iterator operator-(const simd_iterator& it, difference_type x) { return simd_iterator(*it.data, it.index - x); } + /// Advance by the specified offset. constexpr simd_iterator& operator+=(difference_type x) { index += x; return *this; } + + /// Move backward by the specified offset. constexpr simd_iterator& operator-=(difference_type x) { index -= x; return *this; } + /// Compare iterator positions. friend constexpr auto operator<=>(simd_iterator a, simd_iterator b) { return a.index <=> b.index; } + + /// Test iterator equality. friend constexpr bool operator==(simd_iterator a, simd_iterator b) = default; + + /// Test whether the iterator has reached the end. friend constexpr bool operator==(simd_iterator a, std::default_sentinel_t) noexcept { return a.index == static_cast(_Simd::size()); } + /// Return the signed distance from the end sentinel. friend constexpr difference_type operator-(simd_iterator a, std::default_sentinel_t) noexcept { return a.index - static_cast(_Simd::size()); } + /// Return the number of elements remaining before the end sentinel. friend constexpr difference_type operator-(std::default_sentinel_t, simd_iterator a) noexcept { return static_cast(_Simd::size()) - a.index; } }; +/// @} cpp26_iterator + } diff --git a/include/xvec/detail/loadstore.hpp b/include/xvec/detail/loadstore.hpp index 8d607b9..58e2707 100644 --- a/include/xvec/detail/loadstore.hpp +++ b/include/xvec/detail/loadstore.hpp @@ -32,6 +32,17 @@ namespace detail using load_mask_type_iter = typename load_return_type_iter<_Vp, _It>::mask_type; } +/** + * @defgroup cpp26_load_store C++26: Loads and stores + * @brief Transfer vector elements to and from contiguous memory ranges. + * + * Includes partial and unchecked operations, with and without masks, using + * ranges, iterator/count pairs, or iterator/sentinel pairs. + * + * @see https://eel.is/c++draft/simd.load.store + * @{ + */ + /// @brief Load the basic_vec elements from a contiguous sized range, performing /// a suitable conversion if necessary. Two variants are provided (unmasked and /// masked) and these provide the entry points for all the calls to the underlying @@ -39,7 +50,6 @@ namespace detail /// known sizes are converted into special cases that handle those more /// efficiently than a general partial load (e.g., by removing unnecessary /// checks). -/// @ingroup simd_range /// @tparam _Vp The vec vector to return from the load. This specifies the /// number and type of elements. If not provided it will be deduced from the /// range. @@ -48,10 +58,7 @@ namespace detail /// the range has a different value type to the basic_vec then the elements will be /// converted. /// @param r The range from which to copy. -/// @param m A mask controlling which elements will be loaded. Elements without -/// a corresponding active mask will be default initialised. /// @param f The flags to apply to the copy. -///@{ template constexpr detail::load_return_type_range<_Vp, _Range> partial_load(_Range&& r, flags<_Flags...> f = {}) { @@ -81,6 +88,10 @@ constexpr detail::load_return_type_range<_Vp, _Range> partial_load(_Range&& r, f } } +/// @brief Load selected vector elements from a contiguous sized range. +/// @param r The range from which to copy. +/// @param m The mask selecting elements to load. +/// @param f The flags to apply to the copy. template constexpr detail::load_return_type_range<_Vp, _Range> partial_load(_Range&& r, const detail::load_mask_type_range<_Vp, _Range>& m, flags<_Flags...> f = {}) @@ -109,72 +120,96 @@ partial_load(_Range&& r, const detail::load_mask_type_range<_Vp, _Range>& m, fla return detail::load_masked<_R>(target, std::span(r), m, detail::add_unchecked_flag(f)); } } -///@} -/// @brief Provide a set of overloads for different types of load operation, -/// including masked/unmasked, partial/unchecked, iterator+iterator and -/// iterator+size variants. All of these call into the two basic entry points -/// defined above. -/// @ingroup simd_range -/// @tparam _Vp The vec vector to return from the load. This specifies the -/// number and type of elements. If not provided it will be deduced from the -/// range. -/// @tparam _Flags A parameter pack of types identifying properties to apply to this operation. -/// @tparam _Range The contiguous range from which to load the basic_vec values. If -/// the range has a different value type to the basic_vec then the elements will be -/// converted. -/// @param r The range from which to copy. -/// @param m A mask controlling which elements will be loaded. Elements without -/// a corresponding active mask will be default initialised. -/// @param f The flags to apply to the copy. -///@{ +/// @brief Partial load from a contiguous iterator and element count. +/// @param first The beginning of the source range. +/// @param n The source element count. +/// @param f Memory-operation flags. template constexpr detail::load_return_type_iter<_Vp, _It> partial_load(_It first, std::iter_difference_t<_It> n, flags<_Flags...> f = {}) { return partial_load<_Vp>(std::span(first, n), f); } +/// @brief Masked partial load from an iterator and element count. +/// @param first The beginning of the source range. +/// @param n The source element count. +/// @param m The mask selecting elements to load. +/// @param f Memory-operation flags. template constexpr detail::load_return_type_iter<_Vp, _It> partial_load(_It first, std::iter_difference_t<_It> n, const detail::load_mask_type_iter<_Vp, _It>& m, flags<_Flags...> f = {}) { return partial_load<_Vp>(std::span(first, n), m, f); } +/// @brief Partial load from an iterator and sized sentinel. +/// @param first The beginning of the source range. +/// @param last The end of the source range. +/// @param f Memory-operation flags. template _Sent, typename... _Flags> constexpr detail::load_return_type_iter<_Vp, _It> partial_load(_It first, _Sent last, flags<_Flags...> f = {}) { return partial_load<_Vp>(std::span(first, static_cast(last - first)), f); } +/// @brief Masked partial load from an iterator and sized sentinel. +/// @param first The beginning of the source range. +/// @param last The end of the source range. +/// @param m The mask selecting elements to load. +/// @param f Memory-operation flags. template _Sent, typename... _Flags> constexpr detail::load_return_type_iter<_Vp, _It> partial_load(_It first, _Sent last, const detail::load_mask_type_iter<_Vp, _It>& m, flags<_Flags...> f = {}) { return partial_load<_Vp>(std::span(first, static_cast(last - first)), m, f); } +/// @brief Unchecked load from a contiguous sized range. +/// @param r The source range. +/// @param f Memory-operation flags. template constexpr detail::load_return_type_range<_Vp, _Range> unchecked_load(_Range&& r, flags<_Flags...> f = {}) { return partial_load<_Vp>(r, detail::add_unchecked_flag(f)); } +/// @brief Masked unchecked load from a contiguous sized range. +/// @param r The source range. +/// @param m The mask selecting elements to load. +/// @param f Memory-operation flags. template constexpr detail::load_return_type_range<_Vp, _Range> unchecked_load(_Range&& r, const detail::load_mask_type_range<_Vp, _Range>& m, flags<_Flags...> f = {}) { return partial_load<_Vp>(r, m, detail::add_unchecked_flag(f)); } +/// @brief Unchecked load from an iterator and element count. +/// @param first The beginning of the source range. +/// @param n The source element count. +/// @param f Memory-operation flags. template constexpr detail::load_return_type_iter<_Vp, _It> unchecked_load(_It first, std::iter_difference_t<_It> n, flags<_Flags...> f = {}) { return partial_load<_Vp>(std::span(first, n), detail::add_unchecked_flag(f)); } +/// @brief Masked unchecked load from an iterator and element count. +/// @param first The beginning of the source range. +/// @param n The source element count. +/// @param m The mask selecting elements to load. +/// @param f Memory-operation flags. template constexpr detail::load_return_type_iter<_Vp, _It> unchecked_load(_It first, std::iter_difference_t<_It> n, const detail::load_mask_type_iter<_Vp, _It>& m, flags<_Flags...> f = {}) { return partial_load<_Vp>(std::span(first, n), m, detail::add_unchecked_flag(f)); } +/// @brief Unchecked load from an iterator and sized sentinel. +/// @param first The beginning of the source range. +/// @param last The end of the source range. +/// @param f Memory-operation flags. template _Sent, typename... _Flags> constexpr detail::load_return_type_iter<_Vp, _It> unchecked_load(_It first, _Sent last, flags<_Flags...> f = {}) { return partial_load<_Vp>(std::span{first, static_cast(last - first)}, detail::add_unchecked_flag(f)); } +/// @brief Masked unchecked load from an iterator and sized sentinel. +/// @param first The beginning of the source range. +/// @param last The end of the source range. +/// @param m The mask selecting elements to load. +/// @param f Memory-operation flags. template _Sent, typename... _Flags> constexpr detail::load_return_type_iter<_Vp, _It> unchecked_load(_It first, _Sent last, const detail::load_mask_type_iter<_Vp, _It>& m, flags<_Flags...> f = {}) { return partial_load<_Vp>(std::span(first, static_cast(last - first)), m, detail::add_unchecked_flag(f)); } -///@} /// @brief Store the elements from a basic_vec value into a contiguous range, /// performing a suitable conversion if necessary. Both unmasked and masked @@ -182,15 +217,14 @@ unchecked_load(_It first, _Sent last, const detail::load_mask_type_iter<_Vp, _It /// destination is not exceeded. These functions serve as the entry point for /// all overloaded variants of vec store, including masked/unmasked, /// iterator+iterator, iterator+count and all unchecked equivalents. -/// @tparam ..._Flags +/// @tparam _Flags Memory-operation flag types. /// @tparam _Tp The type of the element in the original source. /// @tparam _Abi the Abi of the original vec source. /// @tparam _Range The output range into which to store the elements. If the range has a different /// element type then each value will be converted. /// @param value The simd::vec value to store into the range. /// @param r the range into which to store the simd::vec values. -/// @param flags Control any conversions. -///@{ +/// @param f Flags controlling the memory operation. template requires std::indirectly_writable, _Tp> constexpr void partial_store(const basic_vec<_Tp, _Abi>& value, _Range&& r, flags<_Flags...> f = {}) @@ -214,6 +248,11 @@ constexpr void partial_store(const basic_vec<_Tp, _Abi>& value, _Range&& r, flag } } +/// @brief Store selected vector elements into a contiguous sized range. +/// @param value The source vector. +/// @param r The destination range. +/// @param m The mask selecting elements to store. +/// @param f Memory-operation flags. template requires std::indirectly_writable, _Tp> constexpr void partial_store(const basic_vec<_Tp, _Abi>& value, _Range&& r, @@ -239,72 +278,114 @@ constexpr void partial_store(const basic_vec<_Tp, _Abi>& value, _Range&& r, // } -///@} - -/// @brief Overloads for store the elements from a basic_vec value into a variety of overloaded ranges, with and without masking. -/// @tparam ..._Flags -/// @tparam _Tp The type of the element in the original source. -/// @tparam _Abi the Abi of the original vec source. -/// @tparam _Range The output range into which to store the elements. If the range has a different -/// element type then each value will be converted. -/// @param value The simd::vec value to store into the range. -/// @param r the range into which to store the simd::vec values. -/// @param flags Control any conversions. -///@{ +/// @brief Partial store using a contiguous iterator and element count. +/// @param value The source vector. +/// @param first The beginning of the destination range. +/// @param n The destination element count. +/// @param f Memory-operation flags. template requires std::indirectly_writable<_It, _Tp> constexpr void partial_store(const basic_vec<_Tp, _Abi>& value, _It first, std::iter_difference_t<_It> n, flags<_Flags...> f = {}) { partial_store(value, std::span(first, n), f); } +/// @brief Masked partial store using an iterator and element count. +/// @param value The source vector. +/// @param first The beginning of the destination range. +/// @param n The destination element count. +/// @param m The mask selecting elements to store. +/// @param f Memory-operation flags. template requires std::indirectly_writable<_It, _Tp> constexpr void partial_store(const basic_vec<_Tp, _Abi>& value, _It first, std::iter_difference_t<_It> n, const typename basic_vec<_Tp, _Abi>::mask_type& m, flags<_Flags...> f = {}) { partial_store(value, std::span(first, n), m, f); } +/// @brief Partial store using an iterator and sized sentinel. +/// @param value The source vector. +/// @param first The beginning of the destination range. +/// @param last The end of the destination range. +/// @param f Memory-operation flags. template _Sent, typename... _Flags> requires std::indirectly_writable<_It, _Tp> constexpr void partial_store(const basic_vec<_Tp, _Abi>& value, _It first, _Sent last, flags<_Flags...> f = {}) { partial_store(value, std::span(first, static_cast(last - first)), f); } +/// @brief Masked partial store using an iterator and sized sentinel. +/// @param value The source vector. +/// @param first The beginning of the destination range. +/// @param last The end of the destination range. +/// @param m The mask selecting elements to store. +/// @param f Memory-operation flags. template _Sent, typename... _Flags> requires std::indirectly_writable<_It, _Tp> constexpr void partial_store(const basic_vec<_Tp, _Abi>& value, _It first, _Sent last, const typename basic_vec<_Tp, _Abi>::mask_type& m, flags<_Flags...> f = {}) { partial_store(value, std::span(first, static_cast(last - first)), m, f); } +/// @brief Unchecked store into a contiguous sized range. +/// @param value The source vector. +/// @param r The destination range. +/// @param f Memory-operation flags. template requires std::indirectly_writable, _Tp> constexpr void unchecked_store(const basic_vec<_Tp, _Abi>& value, _Range&& r, flags<_Flags...> f = {}) { partial_store(value, std::span(r), detail::add_unchecked_flag(f)); } +/// @brief Masked unchecked store into a contiguous sized range. +/// @param value The source vector. +/// @param r The destination range. +/// @param m The mask selecting elements to store. +/// @param f Memory-operation flags. template requires std::indirectly_writable, _Tp> constexpr void unchecked_store(const basic_vec<_Tp, _Abi>& value, _Range&& r, const typename basic_vec<_Tp, _Abi>::mask_type& m, flags<_Flags...> f = {}) { partial_store(value, std::span(r), m, detail::add_unchecked_flag(f)); } +/// @brief Unchecked store using an iterator and element count. +/// @param value The source vector. +/// @param first The beginning of the destination range. +/// @param n The destination element count. +/// @param f Memory-operation flags. template requires std::indirectly_writable<_It, _Tp> constexpr void unchecked_store(const basic_vec<_Tp, _Abi>& value, _It first, std::iter_difference_t<_It> n, flags<_Flags...> f = {}) { partial_store(value, std::span(first, n), detail::add_unchecked_flag(f)); } +/// @brief Masked unchecked store using an iterator and element count. +/// @param value The source vector. +/// @param first The beginning of the destination range. +/// @param n The destination element count. +/// @param m The mask selecting elements to store. +/// @param f Memory-operation flags. template requires std::indirectly_writable<_It, _Tp> constexpr void unchecked_store(const basic_vec<_Tp, _Abi>& value, _It first, std::iter_difference_t<_It> n, const typename basic_vec<_Tp, _Abi>::mask_type& m, flags<_Flags...> f = {}) { partial_store(value, std::span(first, n), m, detail::add_unchecked_flag(f)); } +/// @brief Unchecked store using an iterator and sized sentinel. +/// @param value The source vector. +/// @param first The beginning of the destination range. +/// @param last The end of the destination range. +/// @param f Memory-operation flags. template _Sent, typename... _Flags> requires std::indirectly_writable<_It, _Tp> constexpr void unchecked_store(const basic_vec<_Tp, _Abi>& value, _It first, _Sent last, flags<_Flags...> f = {}) { partial_store(value, std::span(first, static_cast(last - first)), detail::add_unchecked_flag(f)); } +/// @brief Masked unchecked store using an iterator and sized sentinel. +/// @param value The source vector. +/// @param first The beginning of the destination range. +/// @param last The end of the destination range. +/// @param m The mask selecting elements to store. +/// @param f Memory-operation flags. template _Sent, typename... _Flags> requires std::indirectly_writable<_It, _Tp> constexpr void unchecked_store(const basic_vec<_Tp, _Abi>& value, _It first, _Sent last, const typename basic_vec<_Tp, _Abi>::mask_type& m, flags<_Flags...> f = {}) { partial_store(value, std::span(first, static_cast(last - first)), m, detail::add_unchecked_flag(f)); } -///@} + +/// @} cpp26_load_store } // namespace _XVEC_NAMESPACE::simd diff --git a/include/xvec/detail/mask.hpp b/include/xvec/detail/mask.hpp index 39955d1..2b02a53 100644 --- a/include/xvec/detail/mask.hpp +++ b/include/xvec/detail/mask.hpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include @@ -23,86 +23,179 @@ namespace _XVEC_NAMESPACE::simd { -/// \defgroup simd_mask_cassign Mask compound assignment operators -/// @brief Compound mask assignment operations. - -/// @defgroup simd_mask_binary Mask binary operators -/// @brief Apply an operator to each pair or respective bits from the input. - -/// \defgroup simd_mask_reduce Mask reduction operations -/// @brief Reduce a simd mask to a single scalar value - -/// @defgroup simd_mask_unary Mask unary operators -/// @brief Apply an operator to each bit in the input to generate a new bitwise mask - -/// @defgroup simd_mask_constructor Mask constructors -/// @brief Construct simd masks - -/// @brief A mask type -/// This allows the vector SIMD classes to handle all the required bit mask type -/// operations in a uniform manner without having to care about the underlying -/// mask type. The mask type can be one of two major styles: +/** + * @defgroup cpp26_mask_overview C++26: Mask overview + * @brief Mask types, element counts, special members, and range access. + * + * @see https://eel.is/c++draft/simd.mask.overview + */ + +/** + * @defgroup cpp26_mask_ctor C++26: Mask constructors + * @brief Construct masks from boolean values, generators, bitsets, integers, and other masks. + * + * @see https://eel.is/c++draft/simd.mask.ctor + */ + +/** + * @defgroup cpp26_mask_conv C++26: Mask conversions + * @brief Convert masks to vectors and packed-bit representations. + * + * @see https://eel.is/c++draft/simd.mask.conv + */ + +/** + * @defgroup cpp26_mask_subscr C++26: Mask subscripting + * @brief Access individual mask elements or select them using an index vector. + * + * @see https://eel.is/c++draft/simd.mask.subscr + */ + +/** + * @defgroup cpp26_mask_unary C++26: Unary mask operators + * @brief Apply unary operations to mask elements. + * + * @see https://eel.is/c++draft/simd.mask.unary + */ + +/** + * @defgroup cpp26_mask_binary C++26: Binary mask operators + * @brief Apply logical and bitwise operations to corresponding mask elements. + * + * @see https://eel.is/c++draft/simd.mask.binary + */ + +/** + * @defgroup cpp26_mask_cassign C++26: Mask compound assignment + * @brief Apply bitwise operations and assign their results. + * + * @see https://eel.is/c++draft/simd.mask.cassign + */ + +/** + * @defgroup cpp26_mask_comparison C++26: Mask comparisons + * @brief Compare corresponding mask elements. + * + * @see https://eel.is/c++draft/simd.mask.comparison + */ + +/** + * @defgroup cpp26_mask_cond C++26: Exposition-only mask selection + * @brief Implementation helpers for element-wise conditional selection. + * + * @see https://eel.is/c++draft/simd.mask.cond + */ + +/** + * @defgroup cpp26_mask_reductions C++26: Mask reductions + * @brief Query mask elements, count selected elements, and find their indexes. + * + * @see https://eel.is/c++draft/simd.mask.reductions + */ + +/** + * @defgroup cpp29_p3440 Create mask from count + * @brief Create a mask with a specified number of leading true elements. + * + * Proposed in P3440 for uses such as handling loop remainders. + * + * @see https://wg21.link/P3440 + */ + +/// @brief A mask containing boolean elements. +/// @ingroup cpp26_mask_overview +/// @tparam _Bytes The associated vector element size in bytes. +/// @tparam _Abi The ABI determining the mask representation and element count. +/// @details Provides a uniform interface over target-specific mask representations. /// -/// Wide mask (e.g., Intel SSE, Intel AVX, Intel AVX2): A full vector of bits -/// with the same size as the SIMD class being used. Each element is all zeros -/// or all ones. Most x86 blend instructions use only the top bit, but having -/// a complete set of bits is useful for performing blend on other targets -/// using bitwise and/or/not/xor instructions. +/// Wide masks, such as those used with Intel SSE and AVX, represent each boolean +/// element using a vector element whose bits are all zero or all one. /// -/// Compact or narrow mask predicate (e.g., Intel AVX-512): A bitset -/// containing only the required number of bits for the number of elements in -/// the SIMD class being used. For example, __m256 treated as `float' elements -/// would have 8 bits. An ExtInt is used to allow the mask to be sized -/// arbitrarily. +/// Compact masks, such as those used with Intel AVX-512, represent each boolean +/// element using a single bit. /// -/// This mask class hides these differences and allows masks to be converted for -/// use in blends, conditionals, selections, as well as operated on using and, -/// or, not, xor, and so on. For more advanced uses (e.g., popcount, any, none, -/// etc), the mask can be exported to a bitset, and bitset's own rich set of -/// operations used, instead of defining them all in this mask class. +/// The class hides these representation differences for logical operations, +/// comparisons, selection, and conversion to packed-bit representations. template class basic_mask { public: + /// Implementation traits for this mask type. + /// @internal using traits = detail::mask_traits; + + /// Compiler-specific storage representation of the mask. + /// @ingroup xvec_interop using builtin_type = typename traits::builtin_type; + /// @addtogroup cpp26_mask_overview + /// @{ + + /// The ABI type of this mask. using abi_type = _Abi; + /// The boolean type of each mask element. using value_type = bool; - using iterator = simd_iterator; ///< An iterator which allows a mask to be treated as a range. + /// Iterator over mask elements. + using iterator = simd_iterator; + + /// Iterator providing read-only access to mask elements. using const_iterator = simd_iterator; - /// Return the number of elements contained in the mask + /// Return the number of elements contained in the mask. static constexpr auto size = size_constant<_Abi::num_elements>{}; + /// @} cpp26_mask_overview + private: /// The builtin mask value. + /// @internal builtin_type mask; public: + /// @addtogroup cpp26_mask_overview + /// @{ + + /// Default-construct a mask. constexpr basic_mask() = default; + + /// Copy-construct a mask. constexpr basic_mask(const basic_mask&) = default; + + /// Move-construct a mask. constexpr basic_mask(basic_mask&&) noexcept = default; + + /// Copy-assign a mask. constexpr basic_mask& operator=(const basic_mask&) = default; + + /// Move-assign a mask. constexpr basic_mask& operator=(basic_mask&&) noexcept = default; + /// @} cpp26_mask_overview + + /// Allow a mask to be constructed from the compiler's own representation. The + /// compiler may use multiple or partial target registers in its + /// representation. This constructor allows a mask to be built from the output + /// of an overloaded operator, a builtin, and so on. + /// @ingroup xvec_interop + constexpr basic_mask(const builtin_type& m) noexcept : mask(m) {} + + /// @addtogroup cpp26_mask_ctor + /// @{ + /// @brief Build a mask from a boolean value. /// @param b The boolean value to broadcast to all mask elements. constexpr explicit basic_mask(std::same_as auto b) noexcept : mask([b] { if (b) return !basic_mask(); else return basic_mask(); }()) {} - /// @brief Build a mask from a set of bits stored in an integral value. - /// Each bit of the mask will be set or cleared as determined by the - /// respective bit of the input integral. If the mask has a size bigger - /// than the number of bits in the supplied integral value the remaining bits - /// will be cleared. - /// @ingroup simd_mask_constructor - /// @param m The unsigned integral value from which to extract the bits into a mask. + /// @brief Build a mask from the bits of an unsigned integral value. + /// Each mask element is initialized from the corresponding input bit. + /// Elements beyond the width of the input value are initialized to false. + /// @param m The unsigned integral value supplying the bits. template requires (!std::same_as) constexpr explicit basic_mask(T m) noexcept : basic_mask([m]() { @@ -112,29 +205,22 @@ class basic_mask return detail::generate_mask_from_unsigned(target, m); }()) {} - /// @brief Create a mask from a mask representing a different vec type. - /// The created mask is equivalent to the supplied input mask, but where - /// the type of element being represented has been changed. Each bit of the - /// new mask is set or cleared corresponding to the respective value of the - /// supplied mask. - /// @ingroup simd_mask_constructor - /// @tparam _UBytes The number of bytes in the source mask - /// @tparam _UAbi The ABI of the source mask elements - /// @param m The input mask from which to create the new mask + /// @brief Convert a mask with the same number of elements. + /// Each output element retains the corresponding input boolean value. + /// @tparam _UBytes The source mask's associated vector element size in bytes. + /// @tparam _UAbi The source mask ABI. + /// @param m The mask to convert. template requires (basic_mask<_UBytes, _UAbi>::size() == size()) explicit constexpr basic_mask(const basic_mask<_UBytes, _UAbi>& m) : mask(detail::convert_mask(target, m)) {} - /// @brief Generate a mask using a generator to compute each bit. - /// For each bit element the generator function is given the index of the - /// element and will return the value (true or false) to be written into that - /// mask element position. If the generator function is constexpr this can be used to - /// construct pre-computed mask values. - /// @ingroup simd_mask_constructor - /// @param fn The generator function to compute each bit. + /// @brief Generate each mask element from its index. + /// @param fn The generator returning a boolean value for each element index. constexpr basic_mask(std::invocable> auto fn) : basic_mask(detail::generate_mask(target, fn)) {} - /// Generate a mask which represents the bottom N bits of the mask. + /// @} cpp26_mask_ctor + + /// Generate a mask with the first _n elements set to true. /// @internal static constexpr basic_mask __mask_from_count(simd_size_type _n) { @@ -146,55 +232,69 @@ class basic_mask return detail::get_n_bit_mask(target, basic_mask(), _n); } - /// @brief Allow a mask to be built from the corresponding bitset. - /// The mask is created such that each bit is set or cleared - /// corresponding to the value of the respective bit from the input bitset. - /// @ingroup simd_mask_constructor - /// @param b The bitset input value + /// @brief Construct a mask from the corresponding bitset. + /// @ingroup cpp26_mask_ctor + /// @param b The bitset supplying the value of each mask element. // :TODO: Not efficient if the bitset isn't constexpr. Need a better way to deal with that eventually. template> T> constexpr basic_mask(const T& b) noexcept : basic_mask([&](simd_size_type idx) { return b[idx]; }) {} - /// Range interface. - ///@{ - // missing begin for non-const + /// @addtogroup cpp26_mask_overview + /// @{ + + /// Return an iterator to the first element. constexpr iterator begin() noexcept { return {*this, 0}; } + + /// Return a const iterator to the first element. constexpr const_iterator begin() const noexcept { return {*this, 0}; } + + /// Return a const iterator to the first element. constexpr const_iterator cbegin() const noexcept { return {*this, 0}; } + + /// Return the end sentinel. constexpr std::default_sentinel_t end() const noexcept { return {}; } + + /// Return the end sentinel. constexpr std::default_sentinel_t cend() const noexcept { return {}; } - ///@} - /// Return the underlying mask value. This is explicit so that no silent conversions are - /// permitted, which often break in unexpected ways. To avoid confusion, the user has to - /// explicitly switch to the underlying type. + /// @} cpp26_mask_overview + + /// Return the underlying mask representation explicitly. + /// @ingroup xvec_interop // :TODO: Maybe to_builtin is sufficient? constexpr explicit operator builtin_type() { return mask; } - /// @brief Convert a mask into a vec value where each element is set to 0 or - /// 1 depending upon the state of its respective bit from the mask. - /// @ingroup simd_constructor + /// @brief Convert the mask to a signed integral vector. + /// Each output element is 1 if the corresponding mask element is true, + /// or 0 otherwise. + /// @ingroup cpp26_mask_conv constexpr operator typename traits::signed_vec_for_mask() const { return detail::mask_to_vec<1, typename traits::element_signed_container_type>(target, *this); } + /// @addtogroup xvec_interop + /// @{ + /// Return the builtin mask value directly. constexpr auto to_builtin() const { return mask; } - /// Construct a mask directly from the underlying builtin. This builtin might - /// be a type which can be used for a standard constructor (e.g., - /// integral-like) so the `from_builtin` ensures that the desired effect is - /// achieved directly. - static constexpr basic_mask from_builtin(const auto& m) { basic_mask bm; bm.mask = traits::truncate_to_size(m); return bm; } + /// Construct a mask directly from its builtin representation. + /// This named operation distinguishes representation conversion from + /// construction using a public value type such as an unsigned integer. + /// @param m The builtin mask representation. + static constexpr basic_mask from_builtin(const builtin_type& m) { basic_mask bm; bm.mask = traits::truncate_to_size(m); return bm; } /// Convert the mask into a register which can be passed to an intrinsic. constexpr auto to_register() const noexcept { return traits::to_register(mask); } - /// Return a bitset representation of the values. std::bitset has a rich API and it makes more - /// sense to use it directly rather than provide similar operations in mask instead (e.g., - /// avoid duplication, alternative implementations, etc.) + /// @} xvec_interop + + /// @addtogroup cpp26_mask_conv + /// @{ + + /// Return a bitset containing the value of each mask element. constexpr std::bitset to_bitset() const noexcept { return detail::mask_to_bitset(target, *this); } - /// Return an unsigned integral representation of the values using ullong. For - /// masks which are bigger than a ullong, the upper bits must be zero. + /// Return an unsigned integral representation of the mask elements. + /// Elements beyond the width of unsigned long long must be false. constexpr unsigned long long to_ullong() const { if (std::is_constant_evaluated()) { @@ -212,105 +312,146 @@ class basic_mask return detail::mask_to_ullong(target, *this); } + /// @} cpp26_mask_conv + + /// @addtogroup cpp26_mask_unary /// @{ - /// @ingroup simd_mask_unary - /// @brief Construct a new mask by applying the unary operator to each bit of the input mask. + + /// Negate each boolean mask element. constexpr basic_mask operator!() const noexcept { return detail::builtin_operator(target, *this, std::bit_not{}); } - + + /// Return a signed integral vector containing 1 for true elements and 0 otherwise. constexpr typename traits::signed_vec_for_mask operator+() const noexcept { return detail::mask_to_vec<1, typename traits::element_signed_container_type>(target, *this); } + /// Return a signed integral vector containing -1 for true elements and 0 otherwise. constexpr typename traits::signed_vec_for_mask operator-() const noexcept { return detail::mask_to_vec<-1, typename traits::element_signed_container_type>(target, *this); } + /// Return the element-wise bitwise complement of the vector produced by unary plus. constexpr typename traits::signed_vec_for_mask operator~() const noexcept { return ~(+*this); } - /// @} - - /// @brief Permute a mask value by indexing it using the unsigned integral indexes supplied in another basic_vec value. - /// @tparam _AbiU The index vec value ABI - /// the permuted basic_vec value, and has the same number of elements as the index basic_vec. - /// @tparam _Up The index type, which must be unsigned integral. - /// @param indexes The indexes by which to permute - /// @return The contents of this mask permuted by the indexes. The output of each element position is this[indexes[iota()]]. + + /// @} cpp26_mask_unary + + /// @addtogroup cpp26_mask_subscr + /// @{ + + /// @brief Select mask elements using an integral index vector. + /// @param indexes The indexes selecting mask elements. + /// @return A mask containing the selected elements. constexpr auto operator[](const vec_integral auto& indexes) const { return permute(*this, indexes); } - /// Return the value of a single element at the given index position. + /// @brief Return the mask element at the specified position. + /// @param pos The element index, which must be less than size() and non-negative. constexpr bool operator[](simd_size_type pos) const& { return detail::subscript(target, *this, pos); } - ///@{ - /// @ingroup simd_mask_binary - /// @param lhs The left hand value in the operation - /// @param rhs The right hand value in the operation - /// @return A mask value which records the result of applying the bit operator to respective bits of the input masks. + /// @} cpp26_mask_subscr + + /// @addtogroup cpp26_mask_binary + /// @{ + + /// Compute the element-wise logical AND. friend constexpr basic_mask operator&&(const basic_mask& lhs, const basic_mask& rhs) noexcept { return detail::builtin_operator(target, lhs, rhs, std::bit_and{}); } + + /// Compute the element-wise logical OR. friend constexpr basic_mask operator||(const basic_mask& lhs, const basic_mask& rhs) noexcept { return detail::builtin_operator(target, lhs, rhs, std::bit_or{}); } + + /// Compute the element-wise bitwise AND. friend constexpr basic_mask operator&(const basic_mask& lhs, const basic_mask& rhs) noexcept { return detail::builtin_operator(target, lhs, rhs, std::bit_and{}); } + + /// Compute the element-wise bitwise OR. friend constexpr basic_mask operator|(const basic_mask& lhs, const basic_mask& rhs) noexcept { return detail::builtin_operator(target, lhs, rhs, std::bit_or{}); } + + /// Compute the element-wise bitwise XOR. friend constexpr basic_mask operator^(const basic_mask& lhs, const basic_mask& rhs) noexcept { return detail::builtin_operator(target, lhs, rhs, std::bit_xor{}); } - /// @} + /// @} cpp26_mask_binary + + /// @addtogroup cpp26_mask_cassign /// @{ - /// @ingroup simd_mask_cassign - /// @param rhs The right hand value of the assignment operator - /// @return The bitwise operation value + + /// Compute the element-wise bitwise AND and assign the result. constexpr basic_mask& operator&=(const basic_mask& rhs) noexcept { *this = *this & rhs; return *this; } + + /// Compute the element-wise bitwise OR and assign the result. constexpr basic_mask& operator|=(const basic_mask& rhs) noexcept { *this = *this | rhs; return *this; } + + /// Compute the element-wise bitwise XOR and assign the result. constexpr basic_mask& operator^=(const basic_mask& rhs) noexcept { *this = *this ^ rhs; return *this; } - /// @} + /// @} cpp26_mask_cassign + + /// @addtogroup cpp26_mask_comparison /// @{ - /// @brief Compare two mask values. - /// @ingroup simd_mask_compare - /// @param lhs The left hand operand - /// @param rhs the right hand operand - /// @return A new mask in which every output mask bit is set to the result of - /// the comparison of respective input mask bits. + + /// Compare corresponding mask elements for equality. friend constexpr basic_mask operator==(const basic_mask& lhs, const basic_mask& rhs) noexcept { return !(lhs ^ rhs); } + + /// Compare corresponding mask elements for inequality. friend constexpr basic_mask operator!=(const basic_mask& lhs, const basic_mask& rhs) noexcept { return lhs ^ rhs; } + + /// Compare corresponding mask elements using less-than. friend constexpr basic_mask operator<(const basic_mask& lhs, const basic_mask& rhs) noexcept { return !lhs && rhs; } + + /// Compare corresponding mask elements using less-than-or-equal. friend constexpr basic_mask operator<=(const basic_mask& lhs, const basic_mask& rhs) noexcept { return !lhs || rhs; } + + /// Compare corresponding mask elements using greater-than. friend constexpr basic_mask operator>(const basic_mask& lhs, const basic_mask& rhs) noexcept { return lhs && !rhs; } + + /// Compare corresponding mask elements using greater-than-or-equal. friend constexpr basic_mask operator>=(const basic_mask& lhs, const basic_mask& rhs) noexcept { return lhs || !rhs; } - /// @} - ///@{ - /// @brief Given two masks, create a new mask which blends respective bits - /// from two inputs according to some selector mask. select works like - /// (is_bit_set ? a : b) for each element. - /// @ingroup simd_mask_cond + /// @} cpp26_mask_comparison + + /// @addtogroup cpp26_mask_cond + /// @{ + + /// @brief Implementation of element-wise selection between two masks. + /// @internal friend constexpr basic_mask simd_select_impl(const basic_mask& m, const basic_mask& if_true, const basic_mask& if_false) noexcept { return detail::select_if_else(target, m, if_true, if_false); } + + /// @brief Implementation of selection between two broadcast boolean values. + /// @internal friend constexpr basic_mask simd_select_impl(const basic_mask& m, std::same_as auto if_true, std::same_as auto if_false) noexcept { return detail::select_if_else(target, m, basic_mask(if_true), basic_mask(if_false)); } + + /// @brief Implementation of element-wise vector selection using a mask. + /// @internal template friend constexpr _Tp simd_select_impl(const basic_mask& m, const _Tp& if_true, const _Tp& if_false) noexcept requires (sizeof(_Tp) == _Bytes) { return detail::select_if_else(target, m, if_true, if_false); } - ///@} + + /// @} cpp26_mask_cond /// @brief Output the mask to a stream as individual bits. - /// @ingroup simd_stream_output + /// @ingroup xvec_stream_output + /// @param stream The destination stream. + /// @param value The mask to output. + /// @return The destination stream. friend std::ostream &operator<<(std::ostream &stream, const basic_mask& value) { stream << value.to_bitset(); return stream; } }; -/// @brief Return true if every bit in the mask is set. Note that a boolean value is treated as a mask with -/// a single element. -/// @ingroup simd_mask_reduce -/// @param mask The mask to query -/// @return True if all the bits in the mask are set, false otherwise. -///@{ +/// @addtogroup cpp26_mask_reductions +/// @{ + +/// @brief Return true if every mask element is true. +/// @param mask The mask to query. +/// @return True if all elements are true. constexpr bool all_of(const mask_type auto& mask) noexcept { if (std::is_constant_evaluated()) { @@ -321,15 +462,14 @@ constexpr bool all_of(const mask_type auto& mask) noexcept { return detail::mask_all_of(target, mask); } +/// @brief Apply all_of to one boolean element. +/// @param b The boolean element. +/// @return b. constexpr bool all_of(std::same_as auto b) noexcept { return b; } -///@} - -/// @brief Return true if any bit in the mask is set. Note that a boolean value is treated as a mask with -/// a single element. -/// @ingroup simd_mask_reduce -/// @param mask The mask to query -/// @return True if any bit in the mask is set. -///@{ + +/// @brief Return true if any mask element is true. +/// @param mask The mask to query. +/// @return True if at least one element is true. constexpr bool any_of(const mask_type auto& mask) noexcept { if (std::is_constant_evaluated()) { @@ -340,15 +480,14 @@ constexpr bool any_of(const mask_type auto& mask) noexcept { return detail::mask_any_of(target, mask); } +/// @brief Apply any_of to one boolean element. +/// @param b The boolean element. +/// @return b. constexpr bool any_of(std::same_as auto b) noexcept { return b; } -///@} - -/// @brief Return true if no bit in the mask is set. Note that a boolean value is treated as a mask with -/// a single element. -/// @ingroup simd_mask_reduce -/// @param mask The mask to query -/// @return True if no bit in the mask is set. -///@{ + +/// @brief Return true if no mask element is true. +/// @param mask The mask to query. +/// @return True if all elements are false. constexpr bool none_of(const mask_type auto& mask) noexcept { if (std::is_constant_evaluated()) { @@ -359,15 +498,14 @@ constexpr bool none_of(const mask_type auto& mask) noexcept { return detail::mask_none_of(target, mask); } +/// @brief Apply none_of to one boolean element. +/// @param b The boolean element. +/// @return !b. constexpr bool none_of(std::same_as auto b) noexcept { return !b; } -///@} - -/// @brief Return the number of mask bits which are set. Note that a boolean value is treated as a mask with -/// a single element. -/// @ingroup simd_mask_reduce -/// @param mask The mask to query -/// @return The total count of set bits in the mask input. -///@{ + +/// @brief Count the true mask elements. +/// @param mask The mask to query. +/// @return The number of true elements. constexpr simd_size_type reduce_count(const mask_type auto& mask) noexcept { if (std::is_constant_evaluated()) { @@ -379,15 +517,15 @@ constexpr simd_size_type reduce_count(const mask_type auto& mask) noexcept { return detail::mask_reduce_count(target, mask); } +/// @brief Count one boolean element. +/// @param b The boolean element. +/// @return 1 if b is true, or 0 otherwise. constexpr simd_size_type reduce_count(std::same_as auto b) noexcept { return +b; } -///@} - -/// @brief Return the index of the lowest set bit. Note that a boolean value is treated as a mask with -/// a single element. -/// @ingroup simd_mask_reduce -/// @param mask The mask to query -/// @return The index of the lowest set bit. -///@{ + +/// @brief Return the index of the first true mask element. +/// @param mask The mask to query. +/// @pre At least one mask element is true. +/// @return The lowest selected index. constexpr simd_size_type reduce_min_index(const mask_type auto& mask) noexcept { if (std::is_constant_evaluated()) { @@ -399,15 +537,15 @@ constexpr simd_size_type reduce_min_index(const mask_type auto& mask) noexcept { return detail::mask_reduce_min_index(target, mask); } +/// @brief Apply reduce_min_index to one boolean element. +/// @pre The input is true. +/// @return 0. constexpr simd_size_type reduce_min_index(std::same_as auto) noexcept { return 0; } -///@} - -/// @brief Return the index of the highest set bit. Note that a boolean value is treated as a mask with -/// a single element. -/// @ingroup simd_mask_reduce -/// @param mask The mask to query -/// @return The index of the highest set bit. -///@{ + +/// @brief Return the index of the last true mask element. +/// @param mask The mask to query. +/// @pre At least one mask element is true. +/// @return The highest selected index. constexpr simd_size_type reduce_max_index(const mask_type auto& mask) noexcept { if (std::is_constant_evaluated()) { @@ -419,13 +557,18 @@ constexpr simd_size_type reduce_max_index(const mask_type auto& mask) noexcept { return detail::mask_reduce_max_index(target, mask); } +/// @brief Apply reduce_max_index to one boolean element. +/// @pre The input is true. +/// @return 0. constexpr simd_size_type reduce_max_index(std::same_as auto) noexcept { return 0; } -///@} -/// @brief Generate a mask with the bottom N bits set. @tparam _Vp The type of -/// the mask to generate, which determines the number of bits in the mask. -/// @param n The number of bits to set in the output mask. If n is bigger than -/// the number of bits in the mask, all bits will be set. +/// @} cpp26_mask_reductions + +/// @brief Generate a mask with its first n elements set to true. +/// @ingroup cpp29_p3440 +/// @tparam _Vp The vector type whose mask is returned, or a scalar type for a boolean result. +/// @param n The number of elements to set. Counts larger than the mask width set every element. +/// @return A prefix mask for vector types, or n > 0 for scalar types. template constexpr auto mask_from_count(simd_size_type n) noexcept { if constexpr (vec_type<_Vp>) { @@ -437,9 +580,11 @@ constexpr auto mask_from_count(simd_size_type n) noexcept { } // CTAD, to convert a basic_mask into a basic_vec, equivalent to decltype(+mask). +/// @brief Deduce a vector type from a mask, equivalent to decltype(+k). +/// @ingroup cpp26_ctor template basic_vec(basic_mask<_Bytes, _Abi> k) -> basic_vec::traits::element_signed_container_type, _Abi>; -} // namespace _XVEC_NAMESPACE::simd +} // namespace _XVEC_NAMESPACE::simd \ No newline at end of file diff --git a/include/xvec/detail/named_permute.hpp b/include/xvec/detail/named_permute.hpp index a9a7c71..1fcfa0d 100644 --- a/include/xvec/detail/named_permute.hpp +++ b/include/xvec/detail/named_permute.hpp @@ -221,15 +221,28 @@ namespace detail { } +/** + * @defgroup cpp29_p3067 Named permutation functions + * @brief Named permutations and related element-manipulation operations for vectors and masks. + * + * Groups xvec's named-permutation family with the proposal + * "Named permutation functions for std::simd". + * + * @see https://wg21.link/P3067 + * @{ + */ + /// Keep the first _Np elements of the input, discarding the remainder. This /// is equivalent to shrinking the vec or mask to a new size. template constexpr auto take(const vec_or_mask_type auto& in) { return detail::permute_take<_Np>(target, in); } -/// Discard the first _Np elements of the input, discarding the remainder. +/// Discard the first _Np elements of the input, returning the remainder. template constexpr auto drop(const vec_or_mask_type auto& in) { return detail::permute_drop<_Np>(target, in); } /// Grow the vec or mask input to be N elements. template constexpr auto grow(const vec_or_mask_type auto& in) { return detail::permute_grow<_Np>(target, in); } + +/// Grow the vec or mask input to be N elements, padding with the supplied value. template constexpr auto grow(const _Sp& in, const typename _Sp::value_type& fill) { using _NewType = resize_t<_Np, _Sp>; @@ -299,10 +312,12 @@ constexpr resize_t<_End - _Begin, _Vp> extract(const _Vp& v) { return detail::ex /// @param child The child container. /// @return A copy of the original container with its original element values in /// the position [_Begin, _Begin + child::size()] replaced by the values from -/// the child. @{ +/// the child. template requires (vec_or_mask_same_element_type<_Parent, _Child>) constexpr _Parent insert(const _Parent& parent, const _Child& child) noexcept { return detail::insert<_Begin>(target, parent, child); } +/// @} cpp29_p3067 + } // namespace _XVEC_NAMESPACE::simd diff --git a/include/xvec/detail/operators.hpp b/include/xvec/detail/operators.hpp index 570f4c3..e22ea9a 100644 --- a/include/xvec/detail/operators.hpp +++ b/include/xvec/detail/operators.hpp @@ -63,7 +63,7 @@ constexpr auto builtin_operator(generic_tag, _Vp lhs, _Vp rhs, _Op op) { r = op(lhsd, rhsd); #endif - if constexpr (mask_operator<_Op>) return _Vp::mask_type::from_builtin(r); + if constexpr (mask_operator<_Op>) return typename _Vp::mask_type(typename _Vp::mask_type::builtin_type(r)); else return _Vp::from_builtin(r); } diff --git a/include/xvec/detail/permute.hpp b/include/xvec/detail/permute.hpp index 50b8e79..53a0bca 100644 --- a/include/xvec/detail/permute.hpp +++ b/include/xvec/detail/permute.hpp @@ -14,9 +14,6 @@ #include #include -/// \defgroup simd_permute Permutation functions for basic_vec -/// @brief Functions to permute and reorder data in and between basic_vec values. - namespace _XVEC_NAMESPACE::simd { namespace detail { @@ -55,8 +52,7 @@ template constexpr auto to_container(const _V& v) return simd_bit_cast<_C>(v); } -/// Concepts to simplify writing the gather/scatter functions. -///@{ +/// Requirements for the gather interfaces. template concept gather_from_requires = (std::same_as<_Vp, std::nullptr_t> @@ -64,18 +60,27 @@ concept gather_from_requires = && simd_same_size<_Vp, _Indexes> && detail::explicitly_convertible_to, typename _Vp::value_type>)); +/// Requirements for the scatter interfaces. template concept scatter_to_requires = (simd_same_size<_Vp, _Indexes> && std::ranges::output_range<_Range, typename _Vp::value_type> && detail::explicitly_convertible_to>); -///@} } // namespace detail +/** + * @defgroup cpp26_permute C++26: Permutations + * @brief Permute vector and mask elements using generated indexes, index vectors, + * selection masks, or indexed memory accesses. + * + * Includes compression, expansion, gather, and scatter operations. + * + * @see https://eel.is/c++draft/simd.permute + * @{ + */ + /// @brief Permute the elements in a vec value using a generator function to compute the indexing. -/// @{ -/// @ingroup simd_permute /// @tparam _NewSize The number of elements required in the permuted output basic_vec. /// @tparam _Vp The type of the basic_vec value to permute /// @param v The value to permute @@ -90,6 +95,12 @@ permute(const _Vp& v, detail::index_generator_function auto&& fn) { constexpr auto new_simd_size = detail::new_simd_size<_NewSize, _Vp::size()>; return detail::generated_permute(target, v, std::forward(fn)); } +/// @brief Permute mask elements using a generator function to compute the indexing. +/// @tparam _NewSize The number of output elements, or zero to retain the input width. +/// @tparam _Mask The input mask type. +/// @param mask The mask to permute. +/// @param fn The index generator function. +/// @return The permuted mask. template constexpr auto permute(const _Mask& mask, detail::index_generator_function auto&& fn) { @@ -104,7 +115,6 @@ permute(const _Mask& mask, detail::index_generator_function auto&& fn) { else return detail::generated_permute(target, mask, std::forward(fn)); } -///@} /// @brief Permute a vec or mask value by the unsigned integral indexes supplied in another basic_vec value. /// @tparam _V The type of the basic_vec or basic_mask value to permute @@ -126,7 +136,6 @@ constexpr resize_t<_I::size, _V> permute(const _V& v, const _I& indexes) /// output. Excess elements will be zeroed. The output basic_vec will have elements /// of the same type as the input basic_vec, and the same number of elements as the /// input mask. -/// @{ /// @tparam _V The vec type /// @param v The values to permute /// @param selector The mask by which to permute. @@ -146,6 +155,11 @@ compress(const _V& v, const typename _V::mask_type& selector) } } +/// @brief Compress selected vector elements and fill the remaining positions. +/// @param v The input vector. +/// @param selector The mask selecting elements. +/// @param fill_value The value used after the packed elements. +/// @return The compressed vector with the specified padding. template constexpr _V compress(const _V& v, const typename _V::mask_type& selector, const typename _V::value_type& fill_value) @@ -179,7 +193,7 @@ constexpr _M compress(const _M& v, const std::type_identity_t<_M>& selector) return detail::compress_mask_by_mask(target, v, selector); } -/// Compress one mask using another mask. +/// Compress one mask using another mask, filling the remaining positions. template constexpr _M compress(const _M& v, const std::type_identity_t<_M>& selector, bool fill_value) { @@ -188,19 +202,13 @@ constexpr _M compress(const _M& v, const std::type_identity_t<_M>& selector, boo else return detail::compress_mask_by_mask(target, v, selector, fill_value); } -///@} - -/// @brief Expand a vec or mask value by a mask. The value returned in an -/// object in which the first [0..reduce_count(selector)) values are copied to -/// those output elements whose respective selector elements are set. Any output -/// elements whose respective selector elements are not set will have the -/// corresponding element from original copied into that position. -/// @{ -/// @tparam _V The vec type -/// @param v The values to permute -/// @param selector The mask by which to permute. -/// @param original The value whose elements should be copied to the output in the positions where the corresponding mask bit is clear. -/// @return The active elements of the vec or mask selected by the mask and packed contiguously into the output. + +/// @brief Expand consecutive input elements into positions selected by a mask. +/// @tparam _V The vec type. +/// @param v The vector supplying consecutive input elements. +/// @param selector The mask selecting output positions. +/// @param original The values retained at positions where the selector is false. +/// @return A vector containing expanded elements and retained original values. template constexpr _V expand(const _V& v, const typename _V::mask_type& selector, const _V& original = {}) @@ -222,6 +230,10 @@ expand(const _V& v, const typename _V::mask_type& selector, const _V& original = } } +/// @brief Expand consecutive mask elements into selected output positions. +/// @param v The mask supplying consecutive input elements. +/// @param selector The mask selecting output positions. +/// @param original The values retained at unselected positions. template constexpr _M expand(const _M& v, const std::type_identity_t<_M>& selector, const _M& original = {}) { @@ -230,19 +242,16 @@ constexpr _M expand(const _M& v, const std::type_identity_t<_M>& selector, const else return detail::expand_mask_by_mask(target, v, selector, original); } -///@} /// @brief Gather the contents of a contiguous range using the integral indexes supplied in another vec value. /// @tparam _Vp A deduced type which the caller can override to specify the return type. This allows type conversions. /// @tparam _Range The range type from which to read. /// @tparam _Indexes The type of the vec indexes used in the gather. -/// @tparam _Flags Flag type controlling the memory access. -/// @param r A contiguous range of known size which references a block of data -/// from which to gather. Only elements inside the range will be accessed. Any -/// indexes outside the range will return undefined values. +/// @tparam _Flags Flag types controlling the memory access. +/// @param r The source range. /// @param indexes The indexes from which to gather. -/// @return A new vec value formed by reading the range from each index element range[idx[iota()]]. -///@{ +/// @param f Flags controlling the memory operation. +/// @return A new vec value formed by reading the range at the supplied indexes. template requires detail::gather_from_requires<_Vp, _Range, _Indexes> constexpr auto @@ -266,6 +275,11 @@ constexpr auto unchecked_gather_from(_Range&& r, const _Indexes& indexes, flags<_Flags...> f = {}) { return partial_gather_from<_Vp>(r, indexes, detail::add_unchecked_flag(f)); } +/// @brief Gather selected elements from a contiguous range. +/// @param r The source range. +/// @param mask The mask enabling index-vector elements. +/// @param indexes The indexes from which to gather. +/// @param f Flags controlling the memory operation. template requires detail::gather_from_requires<_Vp, _Range, _Indexes> constexpr auto @@ -283,7 +297,7 @@ partial_gather_from(_Range&& r, const typename _Indexes::mask_type& mask, return _OutSimd(detail::gather_from(target, r, mask, indexes, f)); } -// Unchecked variant of masked gather_from +/// Unchecked variant of masked gather_from. template requires detail::gather_from_requires<_Vp, _Range, _Indexes> constexpr auto @@ -291,16 +305,14 @@ unchecked_gather_from(_Range&& r, const typename _Indexes::mask_type& mask, const _Indexes& indexes, flags<_Flags...> f = {}) { return partial_gather_from<_Vp>(r, mask, indexes, detail::add_unchecked_flag(f)); } -///@} - /// @brief Scatter the contents of a basic_vec into memory at the integral index positions supplied in another basic_vec value. /// @tparam _Vp The type of the values to scatter to memory. /// @tparam _Indexes The type of the indexes used in the scatter. -/// @tparam _Range The type of the range to which to write. +/// @tparam _Range The range type to which to write. /// @param values The values to scatter to memory. -/// @param r A contiguous range which references a block of data to which to scatter. +/// @param r A contiguous range into which to scatter. /// @param indexes The indexes to which to scatter. -/// @{ +/// @param f Flags controlling the memory operation. template requires detail::scatter_to_requires<_Vp, _Range, _Indexes> constexpr void @@ -314,6 +326,12 @@ partial_scatter_to(const _Vp& values, _Range&& r, const _Indexes& indexes, flags detail::scatter_to(target, values, r, indexes, f); } +/// @brief Scatter selected vector elements into a contiguous range. +/// @param values The values to scatter. +/// @param r The destination range. +/// @param mask The mask enabling index-vector elements. +/// @param indexes The indexes to which to scatter. +/// @param f Flags controlling the memory operation. template requires detail::scatter_to_requires<_Vp, _Range, _Indexes> constexpr void @@ -331,18 +349,20 @@ partial_scatter_to(const _Vp& values, _Range&& r, const typename _Indexes::mask_ detail::scatter_to(target, values, r, mask, indexes, f); } +/// Unchecked variant of scatter. template requires detail::scatter_to_requires<_Vp, _Range, _Indexes> constexpr void unchecked_scatter_to(const _Vp& values, _Range&& r, const _Indexes& indexes, flags<_Flags...> f = {}) { partial_scatter_to(values, r, indexes, detail::add_unchecked_flag(f)); } +/// Unchecked variant of masked scatter. template requires detail::scatter_to_requires<_Vp, _Range, _Indexes> constexpr void unchecked_scatter_to(const _Vp& values, _Range&& r, const typename _Indexes::mask_type& mask, const _Indexes& indexes, flags<_Flags...> f = {}) { partial_scatter_to(values, r, mask, indexes, detail::add_unchecked_flag(f)); } -///@} +/// @} cpp26_permute } // namespace _XVEC_NAMESPACE::simd diff --git a/include/xvec/detail/reduce.hpp b/include/xvec/detail/reduce.hpp index c20c5f8..792154a 100644 --- a/include/xvec/detail/reduce.hpp +++ b/include/xvec/detail/reduce.hpp @@ -83,10 +83,17 @@ inline _Tp reduce_helper(const basic_vec<_Tp, _Abi>& v, _BinaryFn binop) { } // End namespace detail +/** + * @defgroup cpp26_reductions C++26: Reductions + * @brief Reduce vectors to scalar values, with masked and scalar-generic overloads. + * + * @see https://eel.is/c++draft/simd.reductions + * @{ + */ + /// @brief Apply a reduction operation across all elements of the basic_vec value to reduce them to /// a single scalar value. -/// @tparam _Tp The element type of the basic_vec to reduce -/// @tparam _Abi The ABI of the basic_vec to reduce +/// @tparam _V The vector type to reduce /// @tparam _BinaryFn The type of function to apply /// @param v The basic_vec value to reduce into a single element /// @param binop The binary operation to use to generate the reduction (defaults to std::plus) @@ -139,16 +146,17 @@ constexpr _Tp reduce( detail::choose_identity_element<_BinaryFn, _Tp>()) noexcept { return m ? v : identity_element; } -/// @brief Reduction operators for specific types of pre-defined reduction -/// @{ -/// @tparam _Tp The element type of the basic_vec. -/// @tparam _Abi The ABI of the basic_vec -/// @param v The basic_vec value to reduce -/// @return A single value of type _Tp representing the reduction. +/// @brief Return the minimum vector element. +/// @tparam _V The vector type. +/// @param v The vector to reduce. +/// @return The minimum value. template requires requires (_V x) { min(x, x); } constexpr typename _V::value_type reduce_min(const _V& v) noexcept { return reduce(v, detail::minBinaryOperator); } +/// @brief Compute the minimum reduction over selected vector elements. +/// @param v The vector to reduce. +/// @param m The mask selecting elements. template requires requires (_V x) { reduce_min(x); } constexpr typename _V::value_type reduce_min(const _V& v, const typename _V::mask_type& m) noexcept @@ -159,9 +167,15 @@ reduce_min(const _V& v, const typename _V::mask_type& m) noexcept return reduce_min(r); } +/// @brief Return the maximum vector element. +/// @param v The vector to reduce. +/// @return The maximum value. template requires requires (_V x) { max(x, x); } constexpr typename _V::value_type reduce_max(const _V& v) noexcept { return reduce(v, detail::maxBinaryOperator); } +/// @brief Compute the maximum reduction over selected vector elements. +/// @param v The vector to reduce. +/// @param m The mask selecting elements. template requires requires (_V x) { reduce_max(x); } constexpr typename _V::value_type reduce_max(const _V& v, const typename _V::mask_type& m) noexcept @@ -203,6 +217,7 @@ constexpr _Tp reduce_max(const _Tp& v) noexcept { return v; } template requires std::totally_ordered<_Tp> constexpr _Tp reduce_max(const _Tp& v, std::same_as auto m) noexcept { return m ? v : std::numeric_limits<_Tp>::lowest(); } -///@} + +/// @} cpp26_reductions } // namespace _XVEC_NAMESPACE::simd diff --git a/include/xvec/detail/split_concat.hpp b/include/xvec/detail/split_concat.hpp index 3f69afd..08dc319 100644 --- a/include/xvec/detail/split_concat.hpp +++ b/include/xvec/detail/split_concat.hpp @@ -86,14 +86,22 @@ constexpr _Result concatHelper(const _Result& container, const _Sp& head, const } +/** + * @defgroup cpp26_creation C++26: Vector and mask creation + * @brief Split vectors and masks into chunks, or concatenate them into larger values. + * + * @see https://wg21.link/P3441R2 + * @{ + */ + /// Chunk the vec_or_mask_type values into a tuple of smaller values, each of which has /// no more than N elements. The returned tuple will be a set of (size / N) /// full-sized vec or mask values, and one element with (size % N) vec or mask values. If /// there are no remainders then an array of equal-sized simd values will be /// returned. -/// @tparam N The size to split into -/// @param container The svec or mask object to split -/// @return A tuple of vec or mask values of no more than N elements. +/// @tparam _Np The size to split into +/// @param container The vec or mask object to split +/// @return A tuple or array of vec or mask values of no more than _Np elements. template constexpr auto chunk(const _S& container) noexcept { @@ -107,38 +115,31 @@ chunk(const _S& container) noexcept { return r; } -/// Chunk the vec or mask type into a tuple of smaller values, each of which has -/// no more than N elements. The returned tuple will be a set of (size / N) -/// full-sized values, and one element with (size % N) values. If -/// there are no remainders then an array of equal-sized values will be -/// returned. +/// Chunk the vec into smaller values, each of which has no more than +/// _V::size elements. An exact partition returns an array; a partition with a +/// remainder returns a tuple. /// @tparam _V The target vector type that determines the chunk size /// @tparam _Abi The ABI type of the input vec value /// @param s The vec object to split -/// @return A tuple of vec values of no more than _V::size elements. -///@{ +/// @return A tuple or array of vec values of no more than _V::size elements. template constexpr auto chunk(const basic_vec& s) noexcept { return chunk<_V::size>(s); } +/// Chunk the mask into smaller values determined by the target mask width. /// @tparam _M The target mask type that determines the chunk size /// @tparam _Abi The ABI type of the input mask value /// @param m The mask-like object to split -/// @return A tuple of mask-like values of no more than _M::size elements. +/// @return A tuple or array of mask-like values of no more than _M::size elements. template constexpr auto chunk(const basic_mask, _Abi>& m) noexcept { return chunk<_M::size>(m); } -///@} - -/// @brief Concatenate several smaller mask values with the same element type into -/// a single large mask value. -/// The result is the same size as the sum of the incoming containers. -/// @brief Concatenate all the specified mask values into a single mask. -/// @tparam _Tp The element type of the mask -/// @tparam _Abis Multiple parameter ABIs which specify the size of each incoming mask. -/// @param masks Multiple masks to concatenate together. -/// @return A single mask which is the same size as all the incoming -/// mask values put together, and in which their respective bits are -/// concatenated together. + +/// @brief Concatenate several smaller mask values with the same element size +/// into a single large mask value. +/// @tparam _Bytes The element size represented by each mask +/// @tparam _Abis Multiple parameter ABIs which specify the size of each incoming mask +/// @param masks Multiple masks to concatenate together +/// @return A mask containing all incoming mask elements in argument order. template constexpr auto cat(const basic_mask<_Bytes, _Abis>&... masks) noexcept { @@ -167,4 +168,6 @@ constexpr auto cat(const basic_vec<_Tp, _Abis>&... vecs) noexcept return detail::concatHelper<0>(vec<_Tp, _resultSize>(), vecs...); } -} // namespace _XVEC_NAMESPACE::simd +/// @} cpp26_creation + +} // namespace _XVEC_NAMESPACE::simd \ No newline at end of file diff --git a/include/xvec/detail/std_algorithm.hpp b/include/xvec/detail/std_algorithm.hpp index ceaace2..d4ad7cb 100644 --- a/include/xvec/detail/std_algorithm.hpp +++ b/include/xvec/detail/std_algorithm.hpp @@ -16,8 +16,15 @@ namespace _XVEC_NAMESPACE::simd { +/** + * @defgroup cpp26_alg C++26: Algorithms + * @brief Element-wise minimum, maximum, clamping, and selection. + * + * @see https://eel.is/c++draft/simd.alg + * @{ + */ + /// @brief Compute the smaller of each respective vec element from the two input arguments. -/// @ingroup simd_alg /// @tparam _Vp The vec type /// @param lhs The left-hand value to compare /// @param rhs The right-hand value to compare @@ -32,7 +39,6 @@ constexpr _Vp min(const _Vp& lhs, const _Vp& rhs) noexcept { } /// @brief Compute the larger of each respective vec element from the two input arguments. -/// @ingroup simd_alg /// @tparam _Vp The vec type /// @param lhs The left-hand value to compare /// @param rhs The right-hand value to compare @@ -48,7 +54,6 @@ constexpr _Vp max(const _Vp& lhs, const _Vp& rhs) noexcept { /// @brief Compute a pair of vec values giving the smaller and larger /// respective of each corresponding vec element from the two input arguments. -/// @ingroup simd_alg /// @tparam _Vp The vec type. /// @param lhs The left-hand value to compare /// @param rhs The right-hand value to compare @@ -61,7 +66,6 @@ minmax(const _Vp& lhs, const _Vp& rhs) noexcept { return std::make_pair(min(lhs, /// \brief Clamp the input values to be contained within the range [low,high]. If a /// value is less than low it will return low. If a value is greater than high /// it will return high. Other values are unmodified. -/// \ingroup simd_alg /// \tparam _Vp The vec type. /// \param values The values to clamp. /// \param low The low value in the clamping range. @@ -72,19 +76,14 @@ requires std::totally_ordered constexpr _Vp clamp(const _Vp& values, const _Vp& low, const _Vp& high) { return min(max(values, low), high); } -/// @brief Given two vec values, choose one or the other element as output for each element -/// position. select works like (is_bit_set ? a : b) for each element. -/// When the corresponding bit is set in the mask the output element is chosen -/// to be from a, otherwise from b. The second operand defaults to zero if no -/// value is supplied. -/// @ingroup simd_select +/// @brief Select between corresponding elements according to a mask. /// @tparam _M The mask type /// @tparam _T The type of the first value /// @tparam _U The type of the second value /// @param m The mask indicating which elements to select -/// @param if_true The value to use if the mask bit is set -/// @param if_false The value to use if the mask bit is clear. -/// @return A vec where each element is selected from if_true or if_false according to the mask. +/// @param if_true The value to use if the mask element is true +/// @param if_false The value to use if the mask element is false +/// @return A value where each element is selected from if_true or if_false according to the mask. template constexpr auto select(const _M& m, const _T& if_true, const _U& if_false) noexcept -> decltype(simd_select_impl(m, if_true, if_false)) { return simd_select_impl(m, if_true, if_false); } @@ -99,4 +98,6 @@ constexpr auto select(const _M& m, const _T& if_true, const _U& if_false) noexce template constexpr auto select(bool c, const _Tp& a, const _Up& b) -> std::remove_cvref_t { return c ? a : b; } +/// @} cpp26_alg + } // namespace _XVEC_NAMESPACE::simd diff --git a/include/xvec/detail/std_bit.hpp b/include/xvec/detail/std_bit.hpp index 3f94d12..d5d95e4 100644 --- a/include/xvec/detail/std_bit.hpp +++ b/include/xvec/detail/std_bit.hpp @@ -18,21 +18,22 @@ namespace _XVEC_NAMESPACE::simd { -/// \defgroup simd_bit bit header overloads for simd -/// @brief SIMD versions of functions which appear in C++20 bit header. +/** + * @defgroup cpp26_bit C++26: Bit manipulation + * @brief Element-wise bit counting, rotation, power-of-two, and byte-order operations. + * + * @see https://eel.is/c++draft/simd.bit + * @{ + */ -/// @brief Compute the result of rotating each vec element left by a given -/// offset. Also known as circular shift. Values rotated off the end will appear -/// at the other end. If the shift value is negative it is equivalent to -/// shifting right by the negated shift. -/// @{ -/// @ingroup simd_bit -/// @tparam _Up The unsigned vec type to rotate. -/// @tparam _Sp The offset vec type by which to rotate. -/// @param u The value to rotate -/// @param s The offset by which to rotate -/// @return A new simd where every element is the circular shift by s of the -/// corresponding element of the simd value. +/// @brief Rotate each unsigned element left by its corresponding offset. +/// Bits rotated off one end reappear at the other end. +/// Negative offsets rotate in the opposite direction. +/// @tparam _Up The unsigned vector type. +/// @tparam _Sp The integral offset vector type. +/// @param u The input vector. +/// @param s The element-wise rotation offsets. +/// @return A vector containing the rotated elements. template requires (_Up::size() == _Sp::size() && sizeof(typename _Up::value_type) == sizeof(typename _Sp::value_type)) @@ -44,24 +45,23 @@ constexpr _Up rotl(const _Up& u, const _Sp& s) return detail::rotate_left(target, u, s); } +/// @brief Rotate every unsigned element left using a shared offset. +/// @param u The input vector. +/// @param s The shared rotation offset. +/// @return A vector containing the rotated elements. template constexpr _Up rotl(const _Up& u, _Sp s) { using _Rp = std::make_signed_t; return rotl(u, rebind_t<_Rp, _Up>(_Rp(s))); } -///@} - -///@{ -/// @brief Compute the result of rotating each basic_vec element right by a given -/// offset. Also known as circular shift. Values rotated off the end will appear -/// at the other end. If the shift value is negative it is equivalent to -/// shifting left by the negated shift. -/// @ingroup simd_bit -/// @tparam _Up The unsigned vec type to rotate. -/// @tparam _Sp The offset vec type by which to rotate. -/// @param u The value to rotate -/// @param s The offset by which to rotate -/// @return A new basic_vec where every element is the circular shift by s of the -/// corresponding element of the basic_vec value. + +/// @brief Rotate each unsigned element right by its corresponding offset. +/// Bits rotated off one end reappear at the other end. +/// Negative offsets rotate in the opposite direction. +/// @tparam _Up The unsigned vector type. +/// @tparam _Sp The integral offset vector type. +/// @param u The input vector. +/// @param s The element-wise rotation offsets. +/// @return A vector containing the rotated elements. template requires (_Up::size() == _Sp::size() && sizeof(typename _Up::value_type) == sizeof(typename _Sp::value_type)) @@ -73,17 +73,19 @@ constexpr _Up rotr(const _Up& u, const _Sp& s) return detail::rotate_right(target, u, s); } +/// @brief Rotate every unsigned element right using a shared offset. +/// @param u The input vector. +/// @param s The shared rotation offset. +/// @return A vector containing the rotated elements. template constexpr _Up rotr(const _Up& u, _Sp s) { using _Rp = std::make_signed_t; return rotr(u, rebind_t<_Rp, _Up>(_Rp(s))); } -/// @} -/// @brief Return the number of consecutive 0 bits in each element starting from the most significant bit. -/// \ingroup simd_bit -/// @tparam _Vp The type of the vec input. -/// @param v The input value -/// @return A basic_vec containing the number of consecutive 0 bits in each respective element. +/// @brief Count consecutive zero bits from the most significant bit of each element. +/// @tparam _Vp The input vector type. +/// @param v The input vector. +/// @return A signed integral vector containing the counts. template constexpr auto countl_zero(const _Vp& v) noexcept { using _Rp = std::make_signed_t; @@ -93,18 +95,16 @@ constexpr auto countl_zero(const _Vp& v) noexcept { return rebind_t<_Rp, _Vp>(detail::clz(target, v)); } -/// @brief Return the number of consecutive 1 bits in each element starting from the most significant bit. -/// \ingroup simd_bit -/// @tparam _Vp The type of the vec input. -/// @param x The input value -/// @return A basic_vec containing the number of consecutive 1 bits in each respective element. +/// @brief Count consecutive one bits from the most significant bit of each element. +/// @tparam _Vp The input vector type. +/// @param x The input vector. +/// @return A signed integral vector containing the counts. template constexpr auto countl_one(const _Vp& x) noexcept { return countl_zero(~x); } -/// @brief Return the number of consecutive 0 bits in each element starting from the least significant bit. -/// \ingroup simd_bit -/// @tparam _Vp The type of the vec input. -/// @param v The input value -/// @return A basic_vec containing the number of consecutive 0 bits starting from the LSB in each respective element. +/// @brief Count consecutive zero bits from the least significant bit of each element. +/// @tparam _Vp The input vector type. +/// @param v The input vector. +/// @return A signed integral vector containing the counts. template constexpr auto countr_zero(const _Vp& v) noexcept { using _Rp = std::make_signed_t; @@ -119,18 +119,16 @@ constexpr auto countr_zero(const _Vp& v) noexcept { } } -/// @brief Return the number of consecutive 1 bits in each element starting from the least significant bit. -/// \ingroup simd_bit -/// @tparam _Vp The type of the vec input. -/// @param x The input value -/// @return A basic_vec containing the number of consecutive 1 bits from the LSB in each respective element. +/// @brief Count consecutive one bits from the least significant bit of each element. +/// @tparam _Vp The input vector type. +/// @param x The input vector. +/// @return A signed integral vector containing the counts. template constexpr auto countr_one(const _Vp& x) noexcept { return countr_zero(~x); } -/// @brief Count the number of 1 bits in each basic_vec element -// \ingroup simd_bit -/// @tparam _Vp The type of the vec input. -/// @param x The input value -/// @return A basic_vec containing the total number of 1 bits in each respective input element +/// @brief Count the one bits in each element. +/// @tparam _Vp The input vector type. +/// @param x The input vector. +/// @return A signed integral vector containing the population counts. template constexpr auto popcount(const _Vp& x) noexcept { using _Rp = std::make_signed_t; @@ -140,22 +138,19 @@ constexpr auto popcount(const _Vp& x) noexcept { return rebind_t<_Rp, _Vp>(detail::popcount(target, x)); } -/// @brief Check if each element is an integral power-of-2. -// \ingroup simd_bit -/// @tparam _Vp The type of the vec input. -/// @param x The input value -/// @return A mask where each element is set to true if exactly one bit is used in the -/// respective element, or false otherwise. +/// @brief Identify elements that are integral powers of two. +/// @tparam _Vp The input vector type. +/// @param x The input vector. +/// @return A mask that is true where the corresponding element contains exactly one set bit. template constexpr typename _Vp::mask_type has_single_bit(const _Vp& x) noexcept { return detail::has_single_bit(target, x); } -/// @brief Compute the bit width of each element (i.e., how many bits are needed to store the element value). -// \ingroup simd_bit -/// @tparam _Vp The type of the vec input. -/// @param x The input value -/// @return A signed basic_vec containing the width of each respective element +/// @brief Compute the number of bits needed to represent each element. +/// @tparam _Vp The input vector type. +/// @param x The input vector. +/// @return A signed integral vector containing the bit widths. template constexpr rebind_t, _Vp> bit_width(const _Vp& x) noexcept { @@ -163,12 +158,10 @@ bit_width(const _Vp& x) noexcept { return _R(detail::cw::digits> - countl_zero(x)); } -/// @brief For every element compute the smallest integral power of two that is -/// not smaller than the element's value. -// \ingroup simd_bit -/// @tparam _Vp The type of the vec input. -/// @param x The input value -/// @return A signed basic_vec containing the result of std::bit_ceil for that element. +/// @brief Compute the smallest integral power of two not smaller than each element. +/// @tparam _Vp The input vector type. +/// @param x The input vector. +/// @return An unsigned vector containing the element-wise bit ceilings. template constexpr _Vp bit_ceil(const _Vp& x) noexcept { if (std::is_constant_evaluated()) @@ -184,11 +177,11 @@ constexpr _Vp bit_ceil(const _Vp& x) noexcept { } } -/// @brief For every element compute the largest integral power of two that is not greater than the element's value. -// \ingroup simd_bit -/// @tparam _Vp The type of the vec input. -/// @param v The input value -/// @return A signed basic_vec containing the result of std::bit_floor for that element. +/// @brief Compute the largest integral power of two not greater than each element. +/// Zero input elements produce zero output elements. +/// @tparam _Vp The input vector type. +/// @param v The input vector. +/// @return An unsigned vector containing the element-wise bit floors. template constexpr _Vp bit_floor(const _Vp& v) noexcept { using _Tp = typename _Vp::value_type; @@ -201,11 +194,22 @@ constexpr _Vp bit_floor(const _Vp& v) noexcept { } } -/// @brief Bit reverse is now part of C++29. It used to be called bitswap in older releases of this library. -/// \ingroup simd_bit -/// @tparam _Vp The type of the vec input. -/// @param x -/// @return Each element will have its bits reversed. +/// @} cpp26_bit + +/** + * @defgroup cpp29_p3772 Bit reversal + * @brief Reverse the bits within each vector element. + * + * Proposed in P3772R0. + * + * @see https://wg21.link/P3772 + */ + +/// @brief Reverse the bits within each element. +/// @ingroup cpp29_p3772 +/// @tparam _Vp The input vector type. +/// @param x The input vector. +/// @return A vector containing the bit-reversed elements. template constexpr _Vp bit_reverse(const _Vp& x) noexcept { if (std::is_constant_evaluated()) @@ -213,11 +217,11 @@ constexpr _Vp bit_reverse(const _Vp& x) noexcept { else return detail::bitreverse(target, x); } -/// @brief Reverses the bytes in each integer basic_vec element. Byte swap is part of C++23 but is useful enough to include it before then. -/// \ingroup simd_bit -/// @tparam _Vp the type of the vec input. -/// @param v -/// @return Each element will have its bytes reversed. +/// @brief Reverse the bytes within each integral element. +/// @ingroup cpp26_bit +/// @tparam _Vp The input vector type. +/// @param v The input vector. +/// @return A vector containing the byte-reversed elements. template constexpr _Vp byteswap(const _Vp& v) noexcept { if (std::is_constant_evaluated()) @@ -234,18 +238,28 @@ constexpr _Vp byteswap(const _Vp& v) noexcept { return detail::byteswap(target, v); } -///@{ -/// @brief Compute the result of a funnel shift right of two basic_vec values -/// by a given offset. Conceptually concatenates @p high and @p low into a -/// value twice as wide, shifts right by @p s, and returns the low N bits. -/// @ingroup simd_bit -/// @tparam _Up The unsigned vec type of the values to shift. -/// @tparam _Sp The offset vec type by which to shift. -/// @param high The value providing the upper bits of the concatenation. -/// @param low The value providing the lower bits of the concatenation. -/// @param s The offset by which to shift. Precondition: 0 <= s[i] < N for all i. -/// @return A new basic_vec where every element is the funnel shift right of the -/// corresponding elements of @p high and @p low by the corresponding element of @p s. +/** + * @defgroup cpp29_p4010 Funnel shifts + * @brief Shift concatenated pairs of elements and return one element-width result. + * + * Proposed in P4010. + * + * @see https://wg21.link/P4010 + */ + +/// @addtogroup cpp29_p4010 +/// @{ + +/// @brief Funnel shift corresponding element pairs right. +/// Conceptually concatenate each high element with its corresponding low element, +/// shift right, and return the low N bits, where N is the element bit width. +/// @tparam _Up The unsigned vector type. +/// @tparam _Sp The integral shift-count vector type. +/// @param high The upper elements of the concatenation. +/// @param low The lower elements of the concatenation. +/// @param s The element-wise shift counts. +/// @pre For every element i, 0 <= s[i] < N. +/// @return A vector containing the funnel-shift results. template requires (sizeof(typename _Up::value_type) == sizeof(typename _Sp::value_type)) constexpr _Up funnel_shift_right(const _Up& high, const _Up& low, const _Sp& s) @@ -256,23 +270,26 @@ constexpr _Up funnel_shift_right(const _Up& high, const _Up& low, const _Sp& s) return detail::fsr(target, high, low, s); } +/// @brief Funnel shift every element pair right using a shared shift count. +/// @param high The upper elements of the concatenation. +/// @param low The lower elements of the concatenation. +/// @param s The shared shift count. +/// @pre 0 <= s < N, where N is the element bit width. +/// @return A vector containing the funnel-shift results. template constexpr _Up funnel_shift_right(const _Up& high, const _Up& low, _Sp s) { return funnel_shift_right(high, low, _Up(typename _Up::value_type(s))); } -/// @} - -///@{ -/// @brief Compute the result of a funnel shift left of two basic_vec values -/// by a given offset. Conceptually concatenates @p high and @p low into a -/// value twice as wide, shifts left by @p s, and returns the high N bits. -/// @ingroup simd_bit -/// @tparam _Up The unsigned vec type of the values to shift. -/// @tparam _Sp The offset vec type by which to shift. -/// @param high The value providing the upper bits of the concatenation. -/// @param low The value providing the lower bits of the concatenation. -/// @param s The offset by which to shift. Precondition: 0 <= s[i] < N for all i. -/// @return A new basic_vec where every element is the funnel shift left of the -/// corresponding elements of @p high and @p low by the corresponding element of @p s. + +/// @brief Funnel shift corresponding element pairs left. +/// Conceptually concatenate each high element with its corresponding low element, +/// shift left, and return the high N bits, where N is the element bit width. +/// @tparam _Up The unsigned vector type. +/// @tparam _Sp The integral shift-count vector type. +/// @param high The upper elements of the concatenation. +/// @param low The lower elements of the concatenation. +/// @param s The element-wise shift counts. +/// @pre For every element i, 0 <= s[i] < N. +/// @return A vector containing the funnel-shift results. template requires (sizeof(typename _Up::value_type) == sizeof(typename _Sp::value_type)) constexpr _Up funnel_shift_left(const _Up& high, const _Up& low, const _Sp& s) @@ -283,10 +300,17 @@ constexpr _Up funnel_shift_left(const _Up& high, const _Up& low, const _Sp& s) return detail::fsl(target, high, low, s); } +/// @brief Funnel shift every element pair left using a shared shift count. +/// @param high The upper elements of the concatenation. +/// @param low The lower elements of the concatenation. +/// @param s The shared shift count. +/// @pre 0 <= s < N, where N is the element bit width. +/// @return A vector containing the funnel-shift results. template constexpr _Up funnel_shift_left(const _Up& high, const _Up& low, _Sp s) { return funnel_shift_left(high, low, _Up(typename _Up::value_type(s))); } -/// @} + +/// @} cpp29_p4010 } // namespace _XVEC_NAMESPACE::simd @@ -306,4 +330,4 @@ namespace _XVEC_NAMESPACE using simd::popcount; using simd::funnel_shift_left; using simd::funnel_shift_right; -} +} \ No newline at end of file diff --git a/include/xvec/detail/std_complex.hpp b/include/xvec/detail/std_complex.hpp index 3cd704d..5569e0a 100644 --- a/include/xvec/detail/std_complex.hpp +++ b/include/xvec/detail/std_complex.hpp @@ -16,53 +16,78 @@ namespace _XVEC_NAMESPACE::simd { -/// @brief Compute the conjugate of every value (i.e., negate the imaginary part). -/// \ingroup simd_complex -/// @tparam _Vc The vec of complex values. -/// @param value The vec value (complex or real) from which to compute the conjugate. -/// @return A vec in which each complex element is the conjugate of the respective input element. +/** + * @defgroup cpp26_complex_math C++26: Complex math + * @brief Element-wise mathematical functions for complex vectors. + * + * @see https://eel.is/c++draft/simd.complex.math + * @{ + */ + +/// @brief Compute the conjugate of each complex element. +/// @tparam _Vc The complex vector type. +/// @param value The input vector. +/// @return A vector containing the conjugate of each input element. template constexpr _Vc conj(const _Vc& value) { return detail::conj(target, value); } -/// @brief Extract the real components of all the complex elements as a vec value. -/// \ingroup simd_complex -/// @tparam _Vc The vec of complex values. -/// @param value The vec value from which to extract the real elements. -/// @return A vec containing only the real components of every equivalent complex element from the input vec. +/// @brief Extract the real component of each complex element. +/// @tparam _Vc The complex vector type. +/// @param value The input vector. +/// @return A real-valued vector containing the corresponding real components. template constexpr auto real(const _Vc& value) { return value.real(); } -/// @brief Extract the imaginary components of all the complex elements as a vec value. -/// \ingroup simd_complex -/// @tparam _Vc The vec of complex values. -/// @param value The vec value from which to extract the imaginary elements. -/// @return A vec containing only the imaginary components of every equivalent complex element from the input vec. +/// @brief Extract the imaginary component of each complex element. +/// @tparam _Vc The complex vector type. +/// @param value The input vector. +/// @return A real-valued vector containing the corresponding imaginary components. template constexpr auto imag(const _Vc& value) { return value.imag(); } -/// @brief Compute the square of the magnitude of the complex value as a real valued vec. -/// \ingroup simd_complex -/// @tparam _Vc The vec of complex values. -/// @param value The value from which to compute the norm. -/// @return A real-valued vec where every element is the norm of the corresponding input complex vec value. +/// @brief Compute the squared magnitude of each complex element. +/// @tparam _Vc The complex vector type. +/// @param value The input vector. +/// @return A real-valued vector containing the squared magnitude of each input element. template constexpr auto norm(const _Vc& value) { return (value * conj(value)).real(); } -/// @brief Compute the square of the magnitude of the complex value as a real valued vec. -/// \ingroup simd_complex -/// @tparam _Vc The vec of complex values. -/// @param value The value from which to compute the norm. -/// @return A real-valued vec where every element is the norm of the corresponding input complex vec value. +/// @brief Compute the magnitude of each complex element. +/// @tparam _Vc The complex vector type. +/// @param value The input vector. +/// @return A real-valued vector containing the magnitude of each input element. template constexpr auto abs(const _Vc& value) { return sqrt(norm(value)); } -/// @brief Rounding operations implemented for complex numbers. Both the real and imaginary components will be rounded. +/// @} cpp26_complex_math + +/// @addtogroup future_math /// @{ -/// @ingroup simd_complex + +/// @brief Round the real and imaginary components of each element upward. +/// @tparam _Vc The complex vector type. +/// @param value The input vector. +/// @return A complex vector with each component rounded toward positive infinity. template inline _Vc ceil(const _Vc& value) { return simd_bit_cast(ceil(simd_bit_cast(value))); } + +/// @brief Round the real and imaginary components of each element downward. +/// @tparam _Vc The complex vector type. +/// @param value The input vector. +/// @return A complex vector with each component rounded toward negative infinity. template inline _Vc floor(const _Vc& value) { return simd_bit_cast(floor(simd_bit_cast(value))); } + +/// @brief Truncate the real and imaginary components of each element. +/// @tparam _Vc The complex vector type. +/// @param value The input vector. +/// @return A complex vector with each component rounded toward zero. template inline _Vc trunc(const _Vc& value) { return simd_bit_cast(trunc(simd_bit_cast(value))); } + +/// @brief Apply round independently to the real and imaginary components. +/// @tparam _Vc The complex vector type. +/// @param value The input vector. +/// @return A complex vector containing the rounded components. template inline _Vc round(const _Vc& value) { return simd_bit_cast(round(simd_bit_cast(value))); } -///@} + +/// @} future_math /// :TODO: Implement arg, proj, polar, exp, log, log10, [a]sin[h], [a]cos[h], [a]tan[h], pow, sqrt. diff --git a/include/xvec/detail/std_limits.hpp b/include/xvec/detail/std_limits.hpp index 994f3e9..39a8381 100644 --- a/include/xvec/detail/std_limits.hpp +++ b/include/xvec/detail/std_limits.hpp @@ -20,6 +20,21 @@ namespace std using _XVEC_NAMESPACE::simd::basic_vec; +/** + * @defgroup cpp29_p4209 Vector numeric limits + * @brief Numeric properties and broadcast limit values for SIMD vectors. + * + * Described in P4209, "std::numeric_limits for std::basic_vec". + * + * @see https://github.com/danieltowner/std_simd_external_collaboration/blob/18937a79b53cc23c169a335aa493dcaddd71a638/P4209/P4209.bs + * @{ + */ + +/// @brief Extend numeric_limits to vectors whose element type has specialized numeric limits. +/// @tparam _Tp The vector element type. +/// @tparam _Abi The vector ABI. +/// @details Value-returning members broadcast the corresponding scalar limit. +/// Trait members describe the element type. template requires numeric_limits<_Tp>::is_specialized struct numeric_limits> { @@ -31,7 +46,8 @@ struct numeric_limits> { static constexpr bool is_specialized = true; - // Value-returning members: broadcast the scalar limit. + /// Value-returning members: broadcast the scalar limit. + ///@{ static constexpr V min() noexcept { return V(NL::min()); } static constexpr V max() noexcept { return V(NL::max()); } static constexpr V lowest() noexcept { return V(NL::lowest()); } @@ -41,8 +57,10 @@ struct numeric_limits> { static constexpr V quiet_NaN() noexcept { return V(NL::quiet_NaN()); } static constexpr V signaling_NaN() noexcept { return V(NL::signaling_NaN()); } static constexpr V denorm_min() noexcept { return V(NL::denorm_min()); } + ///@} - // Trait members: forward unchanged from numeric_limits. + /// Trait members: forward unchanged from numeric_limits. + ///@{ static constexpr int digits = NL::digits; static constexpr int digits10 = NL::digits10; static constexpr int max_digits10 = NL::max_digits10; @@ -66,6 +84,9 @@ struct numeric_limits> { static constexpr bool traps = NL::traps; static constexpr bool tinyness_before = NL::tinyness_before; static constexpr float_round_style round_style = NL::round_style; + ///@} }; +/// @} cpp29_p4209 + } // namespace std diff --git a/include/xvec/detail/std_math.hpp b/include/xvec/detail/std_math.hpp index 1c70e4b..d2a949a 100644 --- a/include/xvec/detail/std_math.hpp +++ b/include/xvec/detail/std_math.hpp @@ -24,25 +24,40 @@ namespace _XVEC_NAMESPACE::simd { -/// \defgroup simd_math simd C++ math header overloads -/// @brief Support and overloads for simd versions of C++ functions from the math header. - -/// @brief Compute the absolute value of each input vec element. Note that handling abs of an integral is an xvec extension. -/// @ingroup simd_math -/// @tparam _Vp The type of the basic_vec. -/// @param v The vec value -/// @return A simd vec value in which each element is the absolute value of the respective input vec element. -///@{ +/** + * @defgroup cpp26_math C++26: Mathematical functions + * @brief Element-wise mathematical functions for SIMD vectors. + * + * @see https://eel.is/c++draft/simd.math + */ + +/** + * @defgroup future_math Additional mathematical functions + * @brief Additional approximate, fused, integral-classification, and complex operations. + * + * These are xvec extensions, not a claim of adoption into a future standard. + */ + +/// @addtogroup cpp26_math +/// @{ + +/// @brief Compute the absolute value of each floating-point element. +/// @tparam _Vp The input vector type. +/// @param v The input vector. +/// @return A vector containing the absolute values. template constexpr detail::deduced_vec_t<_Vp> abs(const _Vp& v) { return detail::abs(target, v); } + +/// @brief Compute the absolute value of each signed-integral element. +/// @tparam _Vp The input vector type. +/// @param v The input vector. +/// @return A vector containing the absolute values. template constexpr _Vp abs(const _Vp& v) { return detail::abs(target, v); } -///@} - -/// @brief Return a value with the magnitude of the first parameter and the sign of the second. -/// @ingroup simd_math -/// @tparam _Vp The type of the basic_vec -/// @param magnitude The magnitude which will be copied to the output -/// @param sign The sign which will be copied to the output -/// @return A value with the magnitude of the first parameter and the sign of the second. + +/// @brief Combine corresponding magnitudes and signs. +/// @tparam _Vp The input vector type. +/// @param magnitude The vector supplying the magnitudes. +/// @param sign The vector supplying the signs. +/// @return A vector with each magnitude from magnitude and each sign from sign. template constexpr detail::deduced_vec_t<_Vp> copysign(const _Vp& magnitude, const _Vp& sign) { @@ -56,78 +71,89 @@ constexpr detail::deduced_vec_t<_Vp> copysign(const _Vp& magnitude, const _Vp& s return std::bit_cast<_Vp>(tAbs | tSign); } -/// @brief Compute the approximate reciprocal of the input. -/// @ingroup simd_math -/// @tparam _Vp The type of the basic_vec -/// @param v The basic_vec value from which to compute the approximate reciprocal. -/// @return A basic_vec value where every element is the approximate reciprocal of the corresponding input basic_vec element. +/// @} cpp26_math + +/// @addtogroup future_math +/// @{ + +/// @brief Compute the approximate reciprocal of each element. +/// @tparam _Vp The input vector type. +/// @param v The input vector. +/// @return A vector containing approximate reciprocals. template constexpr detail::deduced_vec_t<_Vp> rcp (const _Vp& v) { return detail::rcp(target, v); } -/// @brief Compute the approximate reciprocal square-root of the input. -/// @ingroup simd_math -/// @tparam _Vp The type of the basic_vec -/// @param v The vec value from which to compute the approximate reciprocal square root -/// @return A vec value where every element is the approximate reciprocal -/// square root of the corresponding input vec element. +/// @brief Compute the approximate reciprocal square root of each element. +/// @tparam _Vp The input vector type. +/// @param v The input vector. +/// @return A vector containing approximate reciprocal square roots. template constexpr detail::deduced_vec_t<_Vp> rsqrt(const _Vp& v) { return detail::rsqrt(target, v); } -/// @brief Compute the square-root of the input to within 0.5ULP as guaranteed by IEEE floating-point. -/// @ingroup simd_math -/// @tparam _Vp The type of the basic_vec. -/// @param v The basic_vec value from which to compute the square root -/// @return A basic_vec value where every element is the square root of the corresponding input basic_vec element. +/// @} future_math + +/// @addtogroup cpp26_math +/// @{ + +/// @brief Compute the square root of each element. +/// @tparam _Vp The input vector type. +/// @param v The input vector. +/// @return A vector containing the square roots. template constexpr detail::deduced_vec_t<_Vp> sqrt (const _Vp& v) { return detail::sqrt(target, v); } -/// @brief Compute (lhs * rhs) * acc as if to infinite precision, and rounded -/// only once to fit the result type. The complex overload is an xvec extension. -/// \ingroup simd_math -/// \tparam _Vp The type of the basic_vec -/// \param lhs The left hand value in the multiply. -/// \param rhs The right hand value in the multiply. -/// \param acc The accumulator to which the result of the multiply should be added. -/// \return A new basic_vec value in which each element is formed by applying the fma to each respective element of the inputs. -///@{ +/// @brief Compute (lhs * rhs) + acc element-wise with a single rounding. +/// @tparam _Vp The input vector type. +/// @param lhs The left multiplication operand. +/// @param rhs The right multiplication operand. +/// @param acc The value added to the product. +/// @return A vector containing the fused multiply-add results. template constexpr detail::deduced_vec_t<_Vp> fma (const _Vp& lhs, const _Vp& rhs, const _Vp& acc) { return detail::fma(target, lhs, rhs, acc); } +/// @} cpp26_math + +/// @addtogroup future_math +/// @{ + +/// @brief Compute the complex multiply-add operation element-wise. +/// @tparam _Vp The complex vector type. +/// @param lhs The left multiplication operand. +/// @param rhs The right multiplication operand. +/// @param acc The accumulator. +/// @return A vector containing the complex multiply-add results. template constexpr _Vp fma (const _Vp& lhs, const _Vp& rhs, const _Vp& acc) { return detail::fma(target, lhs, rhs, acc); } -///@} - -/// @brief For all even-indexed elements in the vec, compute (lhs * rhs - acc) and for -/// all odd-indexed elements compute (lhs * rhs + acc). The expressions are -/// computed as if to infinite precision, and rounded only once to fit the -/// result type. This is an xvec extension. -/// \ingroup simd_math -/// \tparam _Vp The type of the basic_vec. -/// \param lhs The left hand value in the multiply. -/// \param rhs The right hand value in the multiply. -/// \param acc The accumulator to which the result of the multiply should be alternatively subtracted or added. -/// \return A new basic_vec value in which each element is formed by applying (lhs * rhs) +- acc to each respective element of the inputs. + +/// @brief Compute lhs * rhs - acc at even indexes and lhs * rhs + acc at odd indexes. +/// Each expression is computed with a single rounding to the result type. +/// @tparam _Vp The input vector type. +/// @param lhs The left multiplication operand. +/// @param rhs The right multiplication operand. +/// @param acc The value alternately subtracted or added. +/// @return A vector containing the alternating fused results. template constexpr detail::deduced_vec_t<_Vp> fmaddsub(const _Vp& lhs, const _Vp& rhs, const _Vp& acc) { return detail::fmaddsub(target, lhs, rhs, acc); } -/// @brief For all even-indexed elements in the basic_vec compute (lhs * rhs + acc) and for -/// all odd-indexed elements compute (lhs * rhs - acc). The expressions are -/// computed as if to infinite precision, and rounded only once to fit the -/// result type. This is an xvec extension. -/// \ingroup simd_math -/// \tparam _Vp The type of the basic_vec -/// \param lhs The left hand value in the multiply. -/// \param rhs The right hand value in the multiply. -/// \param acc The accumulator to which the result of the multiply should be alternatively subtracted or added. -/// \return A new basic_vec value in which each element is formed by applying (lhs * rhs) +- acc to each respective element of the inputs. +/// @brief Compute lhs * rhs + acc at even indexes and lhs * rhs - acc at odd indexes. +/// Each expression is computed with a single rounding to the result type. +/// @tparam _Vp The input vector type. +/// @param lhs The left multiplication operand. +/// @param rhs The right multiplication operand. +/// @param acc The value alternately added or subtracted. +/// @return A vector containing the alternating fused results. template constexpr detail::deduced_vec_t<_Vp> fmsubadd(const _Vp& lhs, const _Vp& rhs, const _Vp& acc) { return detail::fmsubadd(target, lhs, rhs, acc); } -/// @brief For each element compute the smallest integer not less than the given value. -/// @ingroup simd_math -/// @tparam _Vp The type of the basic_vec. -/// @param v The basic_vec value -/// @return A basic_vec value where each element is the smallest integer not less than the given element value. +/// @} future_math + +/// @addtogroup cpp26_math +/// @{ + +/// @brief Round each element toward positive infinity. +/// @tparam _Vp The input vector type. +/// @param v The input vector. +/// @return A vector containing the rounded values. template constexpr detail::deduced_vec_t<_Vp> ceil(const _Vp& v) { #if __has_builtin(__builtin_elementwise_ceil) @@ -137,11 +163,10 @@ constexpr detail::deduced_vec_t<_Vp> ceil(const _Vp& v) { #endif } -/// @brief For each element compute the largest integer no greater than the given value. -/// \ingroup simd_math -/// @tparam _Vp The type of the basic_vec -/// @param v The vec value -/// @return A vec value where each element is the largest integer no greater than the given element value. +/// @brief Round each element toward negative infinity. +/// @tparam _Vp The input vector type. +/// @param v The input vector. +/// @return A vector containing the rounded values. template constexpr detail::deduced_vec_t<_Vp> floor(const _Vp& v) { @@ -152,11 +177,10 @@ constexpr detail::deduced_vec_t<_Vp> floor(const _Vp& v) #endif } -/// @brief For each element compute the nearest integer not greater than the magnitude of the element value. -/// \ingroup simd_math -/// @tparam _Vp The type of the basic_vec -/// @param v The basic_vec value -/// @return A basic_vec value where each element is the nearest integer not greater than the magnitude of the input element. +/// @brief Round each element toward zero. +/// @tparam _Vp The input vector type. +/// @param v The input vector. +/// @return A vector containing the truncated values. template constexpr detail::deduced_vec_t<_Vp> trunc(const _Vp& v) { #if __has_builtin(__builtin_elementwise_trunc) @@ -166,13 +190,10 @@ constexpr detail::deduced_vec_t<_Vp> trunc(const _Vp& v) { #endif } -/// \ingroup simd_math -/// @brief For each element compute the nearest integer value using the current rounding mode. -/// Unlike `round`, this function respects the floating-point environment's current -/// rounding mode. -/// @tparam _Vp The type of the basic_vec -/// @param v The basic_vec value -/// @return A basic_vec value where each element is the nearest integer using the current rounding mode. +/// @brief Round each element to an integer using the current rounding mode. +/// @tparam _Vp The input vector type. +/// @param v The input vector. +/// @return A vector containing the rounded values. template constexpr detail::deduced_vec_t<_Vp> rint(const _Vp& v) { #if __has_builtin(__builtin_elementwise_rint) @@ -182,11 +203,10 @@ constexpr detail::deduced_vec_t<_Vp> rint(const _Vp& v) { #endif } -/// @brief For each element compute the nearest integer value -/// \ingroup simd_math -/// @tparam _Vp -/// @param v The basic_vec value -/// @return A basic_vec value where each element is the nearest integer. +/// @brief Round each element to the nearest integer value. +/// @tparam _Vp The input vector type. +/// @param v The input vector. +/// @return A vector containing the rounded values. template constexpr detail::deduced_vec_t<_Vp> round(const _Vp& v) { #if __has_builtin(__builtin_elementwise_roundeven) @@ -196,10 +216,12 @@ constexpr detail::deduced_vec_t<_Vp> round(const _Vp& v) { #endif } +/// @} cpp26_math + namespace detail { -///@{ -/// Generic implementation of the various classification functions. +/// Generic implementation of NaN classification. +/// @internal template constexpr deduced_mask_t<_Vp> isnan(generic_tag, const _Vp& v) { @@ -215,28 +237,35 @@ constexpr deduced_mask_t<_Vp> isnan(generic_tag, const _Vp& v) constexpr auto fractionMask = typename _Vp::traits::element_container_type(fm); // Check for NaN by using the actual bit-pattern. The exponent must be all - // ones, and the fraction all zeros. Checking a NaN against itself is another + // ones, and the fraction nonzero. Checking a NaN against itself is another // way but is fragile with respect to compiler optimisations. const auto asC = vec_as_container(v); return ((asC & expMask) == expMask) & ((asC & fractionMask) != uint8_t(0)); } +/// Generic implementation of infinity classification. +/// @internal template constexpr detail::deduced_mask_t<_Vp> isinf(generic_tag tag, const _Vp& v) { return !isnan(tag, v) && (abs(v) > std::numeric_limits<_Vp>::max()); } +/// Generic implementation of finite-value classification. +/// @internal template constexpr detail::deduced_mask_t<_Vp> isfinite(generic_tag tag, const _Vp& v) { return !(isinf(tag, v) || isnan(tag, v)); } +/// Generic implementation of normal-value classification. +/// @internal template constexpr detail::deduced_mask_t<_Vp> isnormal(generic_tag, const _Vp& v) { return (abs(v) >= std::numeric_limits<_Vp>::min()) && (abs(v) <= std::numeric_limits<_Vp>::max()); } -///@} +/// Generic implementation of sign-bit classification. +/// @internal template constexpr detail::deduced_mask_t<_Vp> signbit(generic_tag, const _Vp& v) { @@ -249,65 +278,53 @@ constexpr detail::deduced_mask_t<_Vp> signbit(generic_tag, const _Vp& v) // namespace detail -/// @brief Compute a mask which indicates which elements in a vec value represent positive or negative infinities. -/// @ingroup simd_math -/// @tparam _Vp The type of the basic_vec. -/// @param v The basic_vec value to query -/// @return A basic_vec mask where each respective bit of the mask will be set if the -/// corresponding input element is positive or negative infinity, or cleared -/// otherwise. +/// @addtogroup cpp26_math +/// @{ + +/// @brief Identify elements representing positive or negative infinity. +/// @tparam _Vp The input vector type. +/// @param v The input vector. +/// @return A mask whose elements are true for infinite input elements. template constexpr detail::deduced_mask_t<_Vp> isinf(const _Vp& v) { return detail::isinf(target, v); } -/// @brief Compute a basic_vec mask which indicates which elements in a basic_vec value represent a not-a-number floating-point value. -/// @ingroup simd_math -/// @tparam _Vp The type of the basic_vec. -/// @param v The basic_vec value to query -/// @return A mask where each respective bit of the mask will be set if the -/// corresponding input element is not-a-number, or cleared otherwise. +/// @brief Identify elements representing NaN. +/// @tparam _Vp The input vector type. +/// @param v The input vector. +/// @return A mask whose elements are true for NaN input elements. template constexpr detail::deduced_mask_t<_Vp> isnan(const _Vp& v) { return detail::isnan(target, v); } -/// @brief Compute a mask which indicates which elements in a vec value represent -/// finite values. Values which are NaN or infinite will not be finite, and all -/// other floating-point values will be. -/// @ingroup simd_math -/// @tparam _Vp The type of the basic_vec. -/// @param v The simd value to query -/// @return A simd mask where each respective bit of the mask will be set if the -/// corresponding input element is a finite floating-point value or cleared otherwise. +/// @brief Identify finite elements. +/// @tparam _Vp The input vector type. +/// @param v The input vector. +/// @return A mask whose elements are true for inputs that are neither infinite nor NaN. template constexpr detail::deduced_mask_t<_Vp> isfinite(const _Vp& v) { return detail::isfinite(target, v); } -/// @brief Compute a mask which indicates which elements in a vec value -/// represents a normal floating point value, which isn't NaN, zero, sub-normal -/// or infinite. -/// @ingroup simd_math -/// @tparam _Vp The type of the basic_vec. -/// @param v The basic_vec value to query -/// @return A basic_vec mask where each respective bit of the mask will be set if the -/// corresponding input element is a normal number or cleared otherwise. +/// @brief Identify normal floating-point elements. +/// @tparam _Vp The input vector type. +/// @param v The input vector. +/// @return A mask whose elements are true for normal, nonzero finite inputs. template constexpr detail::deduced_mask_t<_Vp> isnormal(const _Vp& v) { return detail::isnormal(target, v); } -/// @brief Compute a basic_vec mask which indicates which elements in a basic_vec value represent a negative value. -/// @ingroup simd_math -/// @tparam _Vp The type of the basic_vec. -/// @param v The basic_vec value to query -/// @return A mask where each respective bit of the mask will be set if the -/// corresponding input element is negative, or cleared otherwise. +/// @brief Identify elements whose sign bit is set. +/// This includes negative zero and negative values of infinity or NaN. +/// @tparam _Vp The input vector type. +/// @param v The input vector. +/// @return A mask containing the sign-bit state of each input element. template constexpr detail::deduced_mask_t<_Vp> signbit(const _Vp& v) { return detail::signbit(target, v); } -/// @brief Compute a basic_vec mask which indicates which elements in a -/// basic_vec value represent a negative value. This is an integral version of -/// the signbit function which doesn't exist in C++26, but is an extension in -/// xvec. -/// @ingroup simd_math -/// @tparam _Vp The type of the basic_vec. -/// @param v The basic_vec value to query -/// @return A mask where each respective bit of the mask will be set if the -/// corresponding input element is negative, or cleared otherwise. +/// @} cpp26_math + +/// @brief Identify negative integral elements. +/// @ingroup future_math +/// @tparam _Vp The integral vector type. +/// @param v The input vector. +/// @return A mask whose elements are true for negative inputs. +/// All output elements are false for unsigned input types. template constexpr typename _Vp::mask_type signbit(const _Vp& v) { if constexpr (vec_unsigned_integral<_Vp>) @@ -316,34 +333,50 @@ constexpr typename _Vp::mask_type signbit(const _Vp& v) { return v < _Vp(); // Signed integer } -/// @brief Comparison functions which produce a mask result. These are the -/// quiet (non-signalling) comparison functions from [simd.math]. They are -/// specified as quiet comparisons (no FE_INVALID raised for unordered -/// operands), and for NaN operands the corresponding result bit is false. For -/// this implementation each function is a thin wrapper over the equivalent -/// relational operator, which already produces a mask and already gives the -/// correct (false) result for NaN-involving comparisons. Only the all-vector -/// overload is provided; the mixed scalar/vector overloads from the standard -/// are not implemented yet. -///@{ +/// @addtogroup cpp26_math +/// @{ + +/// @brief Compare corresponding elements using greater-than. +/// @param x The left operand. +/// @param y The right operand. +/// @return A mask containing the element-wise comparison results. template constexpr detail::deduced_mask_t<_Vp> isgreater(const _Vp& x, const _Vp& y) { return x > y; } +/// @brief Compare corresponding elements using greater-than-or-equal. +/// @param x The left operand. +/// @param y The right operand. +/// @return A mask containing the element-wise comparison results. template constexpr detail::deduced_mask_t<_Vp> isgreaterequal(const _Vp& x, const _Vp& y) { return x >= y; } +/// @brief Compare corresponding elements using less-than. +/// @param x The left operand. +/// @param y The right operand. +/// @return A mask containing the element-wise comparison results. template constexpr detail::deduced_mask_t<_Vp> isless(const _Vp& x, const _Vp& y) { return x < y; } +/// @brief Compare corresponding elements using less-than-or-equal. +/// @param x The left operand. +/// @param y The right operand. +/// @return A mask containing the element-wise comparison results. template constexpr detail::deduced_mask_t<_Vp> islessequal(const _Vp& x, const _Vp& y) { return x <= y; } +/// @brief Identify corresponding elements that compare less or greater. +/// @param x The left operand. +/// @param y The right operand. +/// @return A mask that is false for equal or unordered element pairs. template constexpr detail::deduced_mask_t<_Vp> islessgreater(const _Vp& x, const _Vp& y) { return (x < y) | (x > y); } +/// @brief Identify unordered element pairs. +/// @param x The left operand. +/// @param y The right operand. +/// @return A mask that is true where either corresponding input is NaN. template constexpr detail::deduced_mask_t<_Vp> isunordered(const _Vp& x, const _Vp& y) { return isnan(x) | isnan(y); } -///@} // Basic // :TODO: Move from elsewhere in some cases. @@ -375,6 +408,8 @@ _XVEC_BINARY_MATHS_OP(pow); _XVEC_UNARY_MATHS_OP(erf); _XVEC_UNARY_MATHS_OP(erfc); +/// @} cpp26_math + } // namespace _XVEC_NAMESPACE::simd namespace _XVEC_NAMESPACE @@ -445,4 +480,4 @@ namespace _XVEC_NAMESPACE #undef _XVEC_AVX512_UNARY_MATHS_OP #undef _XVEC_AVX512_BINARY_MATHS_OP #undef _XVEC_AVX512FP16_UNARY_MATHS_OP -#undef _XVEC_AVX512FP16_BINARY_MATHS_OP +#undef _XVEC_AVX512FP16_BINARY_MATHS_OP \ No newline at end of file diff --git a/include/xvec/detail/std_numeric.hpp b/include/xvec/detail/std_numeric.hpp index 51d15c7..75f4afa 100644 --- a/include/xvec/detail/std_numeric.hpp +++ b/include/xvec/detail/std_numeric.hpp @@ -16,17 +16,21 @@ namespace _XVEC_NAMESPACE::simd { -/// \defgroup simd_numeric simd C++ numeric header overloads -/// @brief Support and overloads for basic_vec versions of C++ functions from the numeric header. +/** + * @defgroup cpp29_p2956 SIMD saturating arithmetic + * @brief Saturating arithmetic and element conversion for integral vectors. + * + * Proposed in P2956, "Add saturating library support to std::simd". + * + * @see https://wg21.link/P2956 + * @{ + */ -/// @brief Compute the saturated arithmetic operation on each respective pair of SIMD elements -/// @ingroup simd_numeric +/// @brief Compute the saturated addition of each respective pair of SIMD elements. /// @tparam _Vp The integral basic_vec type. -/// @param lhs The first basic_vec value -/// @param rhs The second basic_vec value -/// @return A basic_vec value in which each element is the saturating operation -/// on each of the respective input elements. -///@{ +/// @param lhs The first basic_vec value. +/// @param rhs The second basic_vec value. +/// @return A basic_vec containing the saturated element-wise sums. template constexpr _Vp saturating_add(const _Vp& lhs, const _Vp& rhs) noexcept { if (std::is_constant_evaluated()) return _Vp([&](auto i) { return detail::saturating_add(lhs[i], rhs[i]); }); @@ -34,6 +38,11 @@ template constexpr _Vp saturating_add(const _Vp& lhs, const _V return detail::saturating_add(target, lhs, rhs); } +/// @brief Compute the saturated subtraction of each respective pair of SIMD elements. +/// @tparam _Vp The integral basic_vec type. +/// @param lhs The first basic_vec value. +/// @param rhs The second basic_vec value. +/// @return A basic_vec containing the saturated element-wise differences. template constexpr _Vp saturating_sub(const _Vp& lhs, const _Vp& rhs) noexcept { if (std::is_constant_evaluated()) return _Vp([&](auto i) { return detail::saturating_sub(lhs[i], rhs[i]); }); @@ -41,18 +50,25 @@ template constexpr _Vp saturating_sub(const _Vp& lhs, const _V return detail::saturating_sub(target, lhs, rhs); } +/// @brief Compute the saturated multiplication of each respective pair of SIMD elements. +/// @tparam _Vp The integral basic_vec type. +/// @param lhs The first basic_vec value. +/// @param rhs The second basic_vec value. +/// @return A basic_vec containing the saturated element-wise products. template constexpr _Vp saturating_mul(const _Vp& lhs, const _Vp& rhs) noexcept { return _Vp([&](auto i) { return detail::saturating_mul(lhs[i], rhs[i]); }); } +/// @brief Compute the saturated division of each respective pair of SIMD elements. +/// @tparam _Vp The integral basic_vec type. +/// @param lhs The dividend basic_vec value. +/// @param rhs The divisor basic_vec value. +/// @return A basic_vec containing the saturated element-wise quotients. template constexpr _Vp saturating_div(const _Vp& lhs, const _Vp& rhs) noexcept { return _Vp([&](auto i) { return detail::saturating_div(lhs[i], rhs[i]); }); } -///@} - /// @brief Compute a basic_vec where every element is converted to the new type, or /// if the value can't be represented then the largest or smallest value of that /// type is used instead, whichever is closer to the original value. -/// @ingroup simd_numeric /// @tparam _Up The target integral element type. /// @tparam _Vp The integral basic_vec type. /// @param v The basic_vec value to convert. @@ -65,4 +81,6 @@ constexpr rebind_t<_Up, _Vp> saturating_cast(const _Vp& v) noexcept { return detail::saturating_cast<_Up>(target, v); } +/// @} cpp29_p2956 + } // namespace _XVEC_NAMESPACE::simd diff --git a/include/xvec/detail/std_rebind.hpp b/include/xvec/detail/std_rebind.hpp index 46b48fb..d158f73 100644 --- a/include/xvec/detail/std_rebind.hpp +++ b/include/xvec/detail/std_rebind.hpp @@ -22,9 +22,6 @@ // separate entity (see detail/core.hpp); the two agree on simd types. namespace _XVEC_NAMESPACE::detail { -/// \defgroup rebind facilities. -/// @brief rebind_cast implementation, as per P3971R1. - /// Rebind simd vector. template constexpr _XVEC_NAMESPACE::simd::rebind_t<_Up, _Vp> rebind_cast(const _Vp& v) @@ -43,6 +40,19 @@ struct RebindCast { namespace _XVEC_NAMESPACE { + /** + * @defgroup cpp29_p3971 Element-type rebinding + * @brief Convert SIMD values to a different element type while preserving their width. + * + * Proposed in P3971, "std::rebind_cast - Generalised Element-Type Conversion + * for Containers and Uniform-Element Types". + * + * @see https://wg21.link/P3971 + * @{ + */ + /// Rebinding CPO. template inline constexpr detail::RebindCast<_Up> rebind_cast{}; + + /// @} cpp29_p3971 } diff --git a/include/xvec/detail/std_utility.hpp b/include/xvec/detail/std_utility.hpp index 53e1a20..ede7928 100644 --- a/include/xvec/detail/std_utility.hpp +++ b/include/xvec/detail/std_utility.hpp @@ -16,24 +16,31 @@ namespace _XVEC_NAMESPACE::simd { -/// \defgroup simd_utility utility header overloads for simd -/// @brief SIMD versions of functions which appear in C++20 utility header. - -/// @brief Converts an enumeration to its underlying type. -/// @tparam _Tp The enumeration type -/// @tparam _Abi The ABI of the simd -/// @param x The simd value of enum type to convert -/// @return A simd value of the underlying type of the enum +/** + * @defgroup cpp29_p2964 SIMD support for enumerations and std::byte + * @brief Facilities associated with the additional element types proposed in P2964. + * + * @see https://wg21.link/P2964 + * @{ + */ + +/// @brief Convert each enumeration element to its underlying type. +/// @tparam _Tp The enumeration type. +/// @tparam _Abi The ABI of the vector. +/// @param x The vector of enumeration values to convert. +/// @return A vector whose elements have the enumeration's underlying type. template requires (std::is_enum_v<_Tp>) constexpr auto to_underlying(const basic_vec<_Tp, _Abi>& x) { return simd_bit_cast>(x); } -/// @brief Converts a std::byte to an integer type. -/// @tparam _Tp The integral type to convert to -/// @tparam _Vp The simd type to convert from, which must be a simd of std::byte -/// @param b The simd value of std::byte type to convert -/// @return A simd value of the specified integer type +/// @brief Convert each std::byte element to an integer type. +/// @tparam _Tp The integral type to convert to. +/// @tparam _Vp The input vector type, whose elements must be std::byte. +/// @param b The vector of byte values to convert. +/// @return A vector whose elements have the specified integer type. template _Vp> constexpr rebind_t<_Tp, _Vp> to_integer(const _Vp& b) noexcept { return rebind_cast<_Tp>(b); } -} // namespace _XVEC_NAMESPACE::simd +/// @} cpp29_p2964 + +} // namespace _XVEC_NAMESPACE::simd \ No newline at end of file diff --git a/include/xvec/generic/generic_impl.hpp b/include/xvec/generic/generic_impl.hpp index 7f54d4c..0733366 100644 --- a/include/xvec/generic/generic_impl.hpp +++ b/include/xvec/generic/generic_impl.hpp @@ -34,7 +34,8 @@ inline constexpr simd_size_type uninit_element = 9999124; // No specific value o /// to generate all multiples of 3 you can do `iota * 3'. Using the constexpr /// nature of iota, along with the constexpr operations and functions makes it /// natural to build simd::vec constants with particular properties. Perhaps even -/// easier than using the generator constructor. @ingroup simd_constructor +/// easier than using the generator constructor. +/// @ingroup cpp26_creation /// @tparam _Tp The vec or arithmetic type for which to generate the iota sequence /// @return A simd::vec or scalar value containing the iota sequence for the type template @@ -258,7 +259,7 @@ select_if_else(compact_mask_tag, const _Mp& if_mask, const _Mp& if_true, const _ /// @param if_true The value to use if the mask bit is set /// @param if_false The value to use if the mask bit is clear /// @return The selected simd mask - template +template constexpr _Mp select_if_else(generic_tag, const _Mp& mask, const _Mp& if_true, const _Mp& if_false) noexcept { return _Mp::from_builtin(mask.to_builtin() ? if_true.to_builtin() : if_false.to_builtin()); } @@ -1144,16 +1145,19 @@ constexpr basic_vec<_Tp, _Abi> mask_to_vec(generic_tag, const basic_mask<_Bytes, static_assert(_Value == 1 || _Value == -1, "Only some values are permitted for mask to vec output"); static_assert(_Bytes == sizeof(_Tp), "Invalid mask or destination - differing sizes"); + using _To = basic_vec<_Tp, _Abi>; + using _B = typename _To::builtin_type; + if constexpr (std::integral<_Tp> && _Value == -1) // The mask is already entirely 0 or 1 bits, so nothing more to do - return basic_vec<_Tp, _Abi>(mask.to_builtin()); + return _To(_B(mask.to_builtin())); else if constexpr (std::integral<_Tp> && _Value == 1) // The mask is entirely 0 or 1 bits so a logical shift will convert the MSB into an LSB. - return basic_vec<_Tp, _Abi>(mask.to_builtin() >> (sizeof(_Tp) * 8 - 1)); + return _To(_B(mask.to_builtin() >> (sizeof(_Tp) * 8 - 1))); else { - constexpr auto _vs = basic_vec<_Tp, _Abi>(_Tp(_Value)); - return select(mask, _vs, basic_vec<_Tp, _Abi>()); + constexpr auto _vs = _To(_Tp(_Value)); + return select(mask, _vs, _To()); } } @@ -1359,7 +1363,7 @@ constexpr auto get_n_bit_mask(compact_mask_tag, const _M&, simd_size_type _n) if constexpr (_M::size <= 64) { const auto clamped = std::min(_M::size(), _n); - return _M::from_builtin(clamped == 64 ? ~0ULL : (1ULL << clamped) - 1); + return _M::from_builtin(typename _M::builtin_type(clamped == 64 ? ~0ULL : (1ULL << clamped) - 1)); } else return _M::from_builtin(_M(true).to_builtin() >> (_M::size - std::min(_n, _M::size()))); @@ -1382,13 +1386,13 @@ template constexpr _Vp popcount(generic_tag, const _Vp& x) noexcept { return _Vp([=](auto i) -> typename _Vp::value_type { return std::popcount(x[i]); }); } -/// @brief Compute the saturated addition of each respective pair of vec elements -/// @ingroup simd_numeric +/// @brief Compute the saturated addition of each respective pair of vector elements. +/// @internal /// @tparam _Tp The integral type of each basic_vec element. -/// @tparam _Abi The ABI of the basic_vec -/// @param lhs The first basic_vec value -/// @param rhs The second basic_vec value -/// @return A basic_vec value in which each element is the saturating addition of the respective input basic_vec elements. +/// @tparam _Abi The ABI of the basic_vec. +/// @param lhs The first basic_vec value. +/// @param rhs The second basic_vec value. +/// @return A basic_vec containing the element-wise saturated sums. template constexpr basic_vec<_Tp, _Abi> saturating_add(generic_tag, const basic_vec<_Tp, _Abi>& lhs, const basic_vec<_Tp, _Abi>& rhs) noexcept { @@ -1420,14 +1424,14 @@ constexpr basic_vec<_Tp, _Abi> saturating_add(generic_tag, const basic_vec<_Tp, #endif } -/// @brief Compute the saturated subtraction of each respective pair of vec elements -/// @ingroup simd_numeric +/// @brief Compute the saturated subtraction of each respective pair of vector elements. +/// @internal /// @tparam _Tp The integral type of each basic_vec element. -/// @tparam _Abi The ABI of the basic_vec -/// @param lhs The first basic_vec value -/// @param rhs The second basic_vec value -/// @return A basic_vec value in which each element is the saturating subtraction of the respective input basic_vec elements. -template +/// @tparam _Abi The ABI of the basic_vec. +/// @param lhs The first basic_vec value. +/// @param rhs The second basic_vec value. +/// @return A basic_vec containing the element-wise saturated differences. +template constexpr basic_vec<_Tp, _Abi> saturating_sub(generic_tag, const basic_vec<_Tp, _Abi>& lhs, const basic_vec<_Tp, _Abi>& rhs) noexcept { #if __has_builtin(__builtin_elementwise_sub_sat) diff --git a/include/xvec/simd b/include/xvec/simd index 788f12e..c1e74d7 100644 --- a/include/xvec/simd +++ b/include/xvec/simd @@ -65,41 +65,100 @@ namespace _XVEC_NAMESPACE::simd // :TODO: Pay more attention to constexpr. Many of the functions can be made to work with constexpr, // but they don't enable that at the moment. -/// \defgroup simd_stream_output Streaming output operators for simd values and masks -/// @brief Output operators to write simd values to standard C++ streams. - -/// \defgroup simd_cassign Compound assignment operators -/// @brief Compound simd assignment operations. - -/// \defgroup simd_constructor Constructors for simd values -/// @brief Constructors for simd values. - -/// \defgroup simd_unary Unary operators -/// @brief Apply a unary operator to every element of a simd value. - -/// \defgroup simd_container Container-like operations -/// @brief Operations which borrow their behaviour from STL containers like vector and array. - -/// \defgroup simd_copy Memory operations -/// @brief Operations which treat the simd as a block of data which can be copied back and forth to memory. - -/// \defgroup simd_range Range operations -/// @brief Operations which allow data to be moved back and forth between a simd and a range. - -/// \defgroup simd_subscript Subscript operators -/// @brief Access a simd element by a subscript index. - -/// \defgroup simd_binary Binary operators -/// @brief Apply the indicated operator to left and right-hand values as a binary element-wise operation. - -/// \defgroup simd_compare Relational comparison operators -/// @brief Apply the given comparison to respective elements of the inputs, generating a mask as an output. - -/// \defgroup simd_complex Complex valued simd operations -/// @brief Allow std::complex<> to be used as the element type of a simd, and mimic the -/// API from std::complex (e.g., norm, abs). - -/// Main simd class. :TODO: Fill in more details. +/** + * @defgroup cpp26_overview C++26: Vector overview + * @brief Vector types, element counts, special members, and range access. + * + * @see https://eel.is/c++draft/simd.overview + */ + +/** + * @defgroup cpp26_ctor C++26: Vector constructors + * @brief Construct vectors from values, ranges, generators, and other vectors. + * + * Includes complex-component construction and vector deduction guides. + * + * @see https://eel.is/c++draft/simd.ctor + */ + +/** + * @defgroup cpp26_subscr C++26: Vector subscripting + * @brief Access individual elements or select elements using an index vector. + * + * @see https://eel.is/c++draft/simd.subscr + */ + +/** + * @defgroup cpp26_complex_access C++26: Complex accessors + * @brief Read or replace the real and imaginary components of vector elements. + * + * @see https://eel.is/c++draft/simd.complex.access + */ + +/** + * @defgroup cpp26_unary C++26: Unary vector operators + * @brief Apply unary operations, including increment and decrement, to vector elements. + * + * @see https://eel.is/c++draft/simd.unary + */ + +/** + * @defgroup cpp26_binary C++26: Binary vector operators + * @brief Element-wise arithmetic, bitwise, and shift operations. + * + * @see https://eel.is/c++draft/simd.binary + */ + +/** + * @defgroup cpp26_cassign C++26: Vector compound assignment + * @brief Apply element-wise operations and assign their results. + * + * @see https://eel.is/c++draft/simd.cassign + */ + +/** + * @defgroup cpp26_comparison C++26: Vector comparisons + * @brief Compare corresponding vector elements to produce a mask. + * + * @see https://eel.is/c++draft/simd.comparison + */ + +/** + * @defgroup cpp26_cond C++26: Exposition-only vector selection + * @brief Implementation helpers for element-wise conditional selection. + * + * @see https://eel.is/c++draft/simd.cond + */ + +/** + * @defgroup cpp29_p2964 Extended element types + * @brief Support for user-defined, enumeration, and byte element types. + * + * Proposed in P2964, "Allowing user-defined types in std::simd". + * Includes conversion of enumeration and byte vectors to integral vectors. + * + * @see https://wg21.link/P2964 + * @{ + */ + +/** + * @defgroup xvec_interop Implementation-specific interoperability + * @brief Convert between xvec objects and compiler-specific representations. + */ + +/** + * @defgroup xvec_stream_output Vector and mask stream output + * @brief Write vector and mask elements to standard streams. + */ + +/** + * @defgroup xvec_unclassified Facilities awaiting classification + * @brief Additional xvec interfaces whose standard or proposal mapping is not yet established. + */ + +/// @brief Vector of elements sharing an element type and ABI. +/// @ingroup cpp26_overview +/// @details Additional element-type support is documented in @ref cpp29_p2964. template class basic_vec { public: @@ -137,6 +196,9 @@ private: public: + /// @addtogroup cpp26_overview + /// @{ + constexpr basic_vec() requires (!vec_complex) = default; constexpr basic_vec() requires (vec_complex) : data() {} @@ -145,11 +207,15 @@ public: constexpr basic_vec& operator=(const basic_vec&) = default; constexpr basic_vec& operator=(basic_vec&&) noexcept = default; + /// @} cpp26_overview + + /// @addtogroup xvec_interop + /// @{ + /// Allow a vec to be constructed from the compiler's own representation. The /// compiler may use multiple or partial target registers in its /// representation. This constructor allows a vec to be built from the output /// of an overloaded operator, a builtin, and so on. - /// @ingroup simd_constructor constexpr basic_vec(const builtin_type& v) noexcept : data(v) {} /// Allow a vec to be constructed from a target register, such as the return @@ -159,19 +225,21 @@ public: /// accepts a builtin type, so in the case where a register is directly /// convertible to a builtin, this would introduce ambiguity and so is /// disabled. - /// @ingroup simd_constructor + /// @ingroup cpp26_ctor explicit constexpr basic_vec(register_type r) noexcept requires (!std::is_convertible_v) : data(traits::from_register(r)) {} + /// @} xvec_interop + + /// @addtogroup cpp26_ctor + /// @{ /// @brief Constructs a basic_vec by reading the contents of an object with the same - /// number of values (e.g., span, C-array, std::array). Both unmasked and masked variants are provided. + /// number of elements (e.g., span, C-array, std::array). /// @tparam _InputSpan The span-like object to copy. - /// @tparam _Flags... Flags which control any conversions necessary. - /// @param in_span The source span-like object - /// @param m A mask to use in the load. Any elements with a cleared mask bit will be value initialised. + /// @tparam _Flags Flags which control any conversions necessary. + /// @param in_span The source span-like object. /// @param f The flags to apply to the copy. - ///@{ template requires (!vec_type<_InputSpan> && detail::span_extent_v<_InputSpan> == size && @@ -184,6 +252,10 @@ public: return detail::load(target, std::span(in_span), detail::add_unchecked_flag(f)); }()) {} + /// @brief Construct a vector from selected elements of a span-like object. + /// @param in_span The source span-like object. + /// @param m The mask selecting elements to load. Unselected elements are value initialized. + /// @param f The flags to apply to the copy. template requires (!vec_type<_InputSpan> && detail::span_extent_v<_InputSpan> == size && @@ -195,39 +267,27 @@ public: else return detail::load_masked(target, std::span(in_span), m, detail::add_unchecked_flag(f)); }()) {} - ///@} - /// @brief Create a basic_vec value in which every element of the basic_vec is set to the single value provided. - /// @ingroup simd_constructor + /// @brief Create a basic_vec value in which every element is set to the single value provided. /// @param v The value to broadcast to every element of the new vec value. template _Up = _Tp> constexpr basic_vec(_Up&& v) noexcept : basic_vec([v](auto) { return _Tp(v); }) {} - /// @brief Create a basic_vec complex value from the supplied basic_vec format real and imaginary values. - /// Each complex basic_vec value will be created by combining the respective elements from the input - /// basic_vec values which represent the real and imaginary components. If no - /// imaginary basic_vec is provided then it will default, which is equivalent to - /// allowing a complex basic_vec value to be created from a real-valued basic_vec. - /// @param r The basic_vec representing the real components of the complex basic_vec to construct - /// @param i The basic_vec representing the imaginary components of the complex basic_vec to construct - /// @ingroup simd_constructor + /// @brief Construct a complex vector from real and imaginary component vectors. + /// Each complex element combines the corresponding real and imaginary elements. + /// If the imaginary vector is omitted, its elements are value initialized. + /// @param r The vector of real components. + /// @param i The vector of imaginary components. constexpr basic_vec(const real_type& r, const real_type& i = {}) noexcept requires (vec_complex) : data(zip(r, i).to_builtin()) {} - /// @brief Construct a new basic_vec value where every element comes from a - /// different basic_vec value, converting the types where necessary. Either - /// both must be complex or neither must be complex. - constructing - /// non-complex from complex is undefined - constructing complex from - /// non-complex is handled in previous constructor. Each basic_vec value will - /// take the converted value of the respective basic_vec input element. + /// @brief Explicitly convert a vector with the same number of elements. + /// Both element types must be complex or neither must be complex. + /// Construction of a complex vector from real components is provided separately. /// - /// Note that two near identical copies are provided, one explicit and one - /// implicit. Ideally the explicit would be made conditional on - /// `implicitly_convertible` but there is a bug in Intel compiler before 2023 - /// version which means this doesn't work properly. - /// @ingroup simd_constructor - /// @param v The value to copy. - ///@{ + /// Two implementations are provided because conditional explicit was not + /// supported correctly by Intel compiler versions before 2023. + /// @param v The value to copy and convert. template requires (!(vec_complex ^ vec_complex<_Vp>) && (_Vp::size() == size()) && @@ -236,6 +296,8 @@ public: explicit constexpr basic_vec(const _Vp& v) noexcept : basic_vec(detail::convert_operator(v)) {} + /// @brief Convert a vector implicitly when its element conversion permits it. + /// @param v The value to copy and convert. template requires (!(vec_complex ^ vec_complex<_Vp>) && (_Vp::size() == size()) && @@ -243,25 +305,36 @@ public: !detail::needs_explicit_conversion) /*no_explicit*/ constexpr basic_vec(const _Vp& v) noexcept : basic_vec(detail::convert_operator(v)) {} - ///@} - - /// @brief Construct a new vec value by using a generator function which - /// computes the value of each element of a vec given its index position. The - /// generator function will accept an index value (0, 1, 2, etc) and returns - /// the value to be written into that position. - /// @param fn A function which accepts a simd_size_type index parameter and which - /// returns a _Tp value representing the element to store at that index. - /// @ingroup simd_constructor + + /// @brief Construct a vector by generating each element from its index. + /// @param fn A function accepting an element index and returning the value + /// to store at that index. constexpr explicit basic_vec(detail::generator_invocable auto&& fn) : basic_vec(detail::generate(fn)) {} - /// Range interface. - ///@{ + /// @} cpp26_ctor + + /// @addtogroup cpp26_overview + /// @{ + + /// Return an iterator to the first element. constexpr iterator begin() noexcept { return {*this, 0}; } + + /// Return a const iterator to the first element. constexpr const_iterator begin() const noexcept { return {*this, 0}; } + + /// Return a const iterator to the first element. constexpr const_iterator cbegin() const noexcept { return {*this, 0}; } + + /// Return the end sentinel. constexpr std::default_sentinel_t end() const noexcept { return {}; } + + /// Return the end sentinel. constexpr std::default_sentinel_t cend() const noexcept { return {}; } - ///@} + + /// @} cpp26_overview + + /// @addtogroup xvec_interop + /// @{ /// @brief Allow the vec to be turned into the closest matching target vec register type. /// This will return the smallest target register that can contain all the elements of the vec. @@ -275,97 +348,111 @@ public: /// @brief Return the builtin value. constexpr builtin_type to_builtin() const { return data; } + /// @brief Construct a vector from its builtin representation. static constexpr basic_vec from_builtin(const builtin_type& v) noexcept { return basic_vec(v); } - /// @brief Access the index at the given position of the basic_vec. Undefined if the position is outside the basic_vec size. - /// \ingroup simd_subscript - /// \param pos The position of the accessed element. + /// @} xvec_interop + + /// @addtogroup cpp26_subscr + /// @{ + + /// @brief Access the element at the specified position. + /// @param pos The element index, which must be less than size() and non-negative. constexpr value_type operator[](simd_size_type pos) const { return detail::subscript(target, *this, pos); } - /// @brief Index a basic_vec value by the unsigned integral indexes supplied in - /// another basic_vec value. This is equivalent to a permutation. - /// @tparam _AbiU The index basic_vec value ABI - /// the permuted vec value, and has the same number of elements as the index basic_vec. - /// @tparam _Up The index type, which must be unsigned integral. - /// @param v The basic_vec value to permute - /// @param indexes The indexes by which to permute - /// @return The contents of v permuted by the indexes. The output of each element position is v[idx[iota()]]. + /// @brief Select vector elements using an integral index vector. + /// @param indexes The indexes by which to permute. + /// @return The selected elements, with the same element count as indexes. constexpr auto operator[](const vec_integral auto& indexes) const { return permute(*this, indexes); } - /// @brief Given two vectors, choose one or other element as output for each element - /// position. select works like (is_bit_set ? a : b) for each element. - /// When the corresponding bit is set in the mask the output element is chosen - /// to be from a, otherwise from b. The second operand defaults to zero if no - /// value is supplied. Note that select has the opposite ordering sense to - /// blend. - /// @ingroup simd_select + /// @} cpp26_subscr + + /// @brief Implementation of element-wise vector selection. + /// @ingroup cpp26_cond + /// @internal friend constexpr basic_vec simd_select_impl(const mask_type& m, const basic_vec& if_true, const basic_vec& if_false) noexcept { return detail::select_if_else(target, m, if_true, if_false); } - /// @brief Perform a logical not on every element of the basic_vec to generate a mask. - /// \ingroup simd_unary - /// \param v The value to which to apply logical not. - /// \return A new mask_type value in which each element is formed by applying - /// operator! to each respective element of the inputs. + /// @addtogroup cpp26_unary + /// @{ + + /// @brief Apply logical not to each vector element to produce a mask. constexpr mask_type operator!() const noexcept requires requires (value_type a) { {!a} -> std::same_as; } { return detail::do_operator>(*this); } - /// @brief Perform a bitwise not on every element of the basic_vec. - /// \ingroup simd_unary - /// \param v The value to which to apply bitwise not. - /// \return A new basic_vec value in which each element is formed by applying the bitwise not to each respective element of the inputs. + /// @brief Apply bitwise not to each vector element. constexpr basic_vec operator~() const noexcept requires detail::supported_unary_op> { return detail::do_operator>(*this); } - /// @{ - /// @brief Apply a given unary operation to each element of a basic_vec value. - /// \ingroup simd_unary - /// \return A new basic_vec value in which each respective element is formed by applying the operator to each respective element of the inputs. + /// @brief Negate each vector element. constexpr basic_vec operator-() const noexcept requires detail::supported_unary_op> { return detail::do_operator>(*this); } + /// Return a copy of the vector. constexpr basic_vec operator+() const noexcept { return *this; } + + /// Increment each element and return the updated vector. constexpr basic_vec& operator++() noexcept requires requires (basic_vec v) { v + basic_vec(_Tp(1)); } { *this = *this + basic_vec(_Tp(1)); return *this; } + + /// Increment each element and return the original vector. constexpr basic_vec operator++(int) noexcept requires requires (basic_vec v) { v + basic_vec(_Tp(1)); } { const auto original = *this; *this = *this + basic_vec(_Tp(1)); return original; } + + /// Decrement each element and return the updated vector. constexpr basic_vec& operator--() noexcept requires requires (basic_vec v) { v - basic_vec(_Tp(1)); } { *this = *this - basic_vec(_Tp(1)); return *this; } + + /// Decrement each element and return the original vector. constexpr basic_vec operator--(int) noexcept requires requires (basic_vec v) { v - basic_vec(_Tp(1)); } { const auto original = *this; *this = *this - basic_vec(_Tp(1)); return original; } - /// @} - /// \ingroup simd_binary - /// @brief Invoke a binary arithmetic operator on two basic_vec values, applying the operation to each pair of respective elements. - /// \param lhs The left hand value of the binary expression - /// \param rhs The right hand value of the binary expression - /// \return A new basic_vec value in which each respective element is formed by applying the operator to each respective element of the inputs. + /// @} cpp26_unary + + /// @addtogroup cpp26_binary /// @{ + + /// Add corresponding elements. friend constexpr basic_vec operator+(const basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_binary_op> { return detail::do_operator>(lhs, rhs); } + + /// Subtract corresponding elements. friend constexpr basic_vec operator-(const basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_binary_op> { return detail::do_operator>(lhs, rhs); } + + /// Multiply corresponding elements. friend constexpr basic_vec operator*(const basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_binary_op> { return detail::do_operator>(lhs, rhs); } + + /// Divide corresponding elements. friend constexpr basic_vec operator/(const basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_binary_op> { return detail::do_operator>(lhs, rhs); } + + /// Compute the remainder for corresponding elements. friend constexpr basic_vec operator%(const basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_binary_op> { return detail::do_operator>(lhs, rhs); } + /// Compute the bitwise AND of corresponding elements. friend constexpr basic_vec operator&(const basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_binary_op> { return detail::do_operator>(lhs, rhs); } + + /// Compute the bitwise OR of corresponding elements. friend constexpr basic_vec operator|(const basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_binary_op> { return detail::do_operator>(lhs, rhs); } + + /// Compute the bitwise XOR of corresponding elements. friend constexpr basic_vec operator^(const basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_binary_op> { return detail::do_operator>(lhs, rhs); } - ///@} - /// @brief Special multiply operators for scalar-complex products. It is more efficient to - /// handle this explicitly. - ///@{ + /// @} cpp26_binary + + /// @addtogroup xvec_unclassified + /// @{ + + /// Multiply each complex element by a real scalar. friend constexpr basic_vec operator*(const basic_vec& lhs, const detail::complex_element_type<_Tp>& rhs) noexcept requires (vec_complex) { @@ -373,140 +460,175 @@ public: return std::bit_cast(t); } + /// Multiply a real scalar by each complex element. friend constexpr basic_vec operator*(const detail::complex_element_type<_Tp>& lhs, const basic_vec& rhs) noexcept requires (vec_complex) { return rhs * lhs; } + /// Multiply each complex element by a real scalar and assign the result. friend constexpr basic_vec& operator*=(basic_vec& lhs, const detail::complex_element_type<_Tp>& rhs) noexcept requires (vec_complex) { lhs = lhs * rhs; return lhs; } - ///@} - /// @brief Binary relational operators - /// \ingroup simd_binary - /// \param lhs The left hand value of the binary comparison expression - /// \param rhs The right hand value of the binary comparison expression - /// \return A mask which encodes the result of each element-wise comparison in its respective boolean element. + /// @} xvec_unclassified + + /// @addtogroup cpp26_comparison /// @{ + + /// Compare corresponding elements for equality. friend constexpr mask_type operator==(const basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_relational_op> { return detail::do_operator>(lhs, rhs); } + + /// Compare corresponding elements for inequality. friend constexpr mask_type operator!=(const basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_relational_op> { return detail::do_operator>(lhs, rhs); } + + /// Compare corresponding elements using less-than. friend constexpr mask_type operator< (const basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_relational_op> { return detail::do_operator>(lhs, rhs); } + + /// Compare corresponding elements using less-than-or-equal. friend constexpr mask_type operator<=(const basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_relational_op> { return detail::do_operator>(lhs, rhs); } + + /// Compare corresponding elements using greater-than. friend constexpr mask_type operator> (const basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_relational_op> { return detail::do_operator>(lhs, rhs); } + + /// Compare corresponding elements using greater-than-or-equal. friend constexpr mask_type operator>=(const basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_relational_op> { return detail::do_operator>(lhs, rhs); } - ///@} - /// Compound assignment operator + /// @} cpp26_comparison + + /// @addtogroup cpp26_cassign /// @{ - /// \ingroup simd_cassign - /// \param rhs The right hand value of the binary expression - /// \return A new vec value in which each respective element is formed by applying the operator to each respective element of the inputs. + + /// Add corresponding elements and assign the result. friend constexpr basic_vec& operator+=(basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_binary_op> { lhs = lhs + rhs; return lhs; } + + /// Subtract corresponding elements and assign the result. friend constexpr basic_vec& operator-=(basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_binary_op> { lhs = lhs - rhs; return lhs; } + + /// Multiply corresponding elements and assign the result. friend constexpr basic_vec& operator*=(basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_binary_op> { lhs = lhs * rhs; return lhs; } + + /// Divide corresponding elements and assign the result. friend constexpr basic_vec& operator/=(basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_binary_op> { lhs = lhs / rhs; return lhs; } + + /// Compute element-wise remainders and assign the result. friend constexpr basic_vec& operator%=(basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_binary_op> { lhs = lhs % rhs; return lhs; } + + /// Compute the element-wise bitwise AND and assign the result. friend constexpr basic_vec& operator&=(basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_binary_op> { lhs = lhs & rhs; return lhs; } + + /// Compute the element-wise bitwise OR and assign the result. friend constexpr basic_vec& operator|=(basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_binary_op> { lhs = lhs | rhs; return lhs; } + + /// Compute the element-wise bitwise XOR and assign the result. friend constexpr basic_vec& operator^=(basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_binary_op> { lhs = lhs ^ rhs; return lhs; } - /// @} - /// Shift operators - /// @{ - /// \ingroup simd_binary - /// \param lhs The left-hand value of the binary expression - /// \param rhs The right-hand value of the binary expression - /// \param shift The shift offset, which must be an unsigned value. - /// \return A new basic_vec value in which each respective element is formed by applying the shift operator to each respective element of the inputs. + /// @} cpp26_cassign + + /// @addtogroup cpp26_binary /// @{ + + /// Shift elements left by corresponding element-wise amounts. friend constexpr basic_vec operator<<(const basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_binary_op> { return detail::do_operator>(lhs, rhs); } + + /// Shift elements right by corresponding element-wise amounts. friend constexpr basic_vec operator>>(const basic_vec& lhs, const basic_vec& rhs) noexcept requires detail::supported_binary_op> { return detail::do_operator>(lhs, rhs); } + /// Shift every element left by a shared amount. friend constexpr basic_vec operator<<(const basic_vec& lhs, simd_size_type rhs) noexcept requires detail::supported_binary_op> { return lhs << basic_vec(value_type(rhs)); } + + /// Shift every element right by a shared amount. friend constexpr basic_vec operator>>(const basic_vec& lhs, simd_size_type rhs) noexcept requires detail::supported_binary_op> { return lhs >> basic_vec(value_type(rhs)); } - /// @} + /// @} cpp26_binary + /// @addtogroup cpp26_cassign /// @{ - /// \ingroup simd_cassign - /// \param shift The value by which to shift. - /// \return A new vec value in which each respective element is formed by applying the operator to each respective element of the inputs. + + /// Shift elements left by element-wise amounts and assign the result. friend constexpr basic_vec& operator<<=(basic_vec& lhs, const basic_vec& shift) noexcept requires detail::supported_binary_op> { lhs = lhs << shift; return lhs; } + + /// Shift elements right by element-wise amounts and assign the result. friend constexpr basic_vec& operator>>=(basic_vec& lhs, const basic_vec& shift) noexcept requires detail::supported_binary_op> { lhs = lhs >> shift; return lhs; } + + /// Shift every element left by a shared amount and assign the result. friend constexpr basic_vec& operator<<=(basic_vec& lhs, simd_size_type shift) noexcept requires detail::supported_binary_op> { lhs = lhs << shift; return lhs; } + + /// Shift every element right by a shared amount and assign the result. friend constexpr basic_vec& operator>>=(basic_vec& lhs, simd_size_type shift) noexcept requires detail::supported_binary_op> { lhs = lhs >> shift; return lhs; } - /// @} - /// @brief Return a vec containing only the real values from this complex object. - /// @return A new vec with the same number of elements as the original object but containing only the real components. - /// @ingroup simd_complex + /// @} cpp26_cassign + + /// @addtogroup cpp26_complex_access + /// @{ + + /// @brief Return the real components of the complex elements. + /// @return A real-valued vector with the same number of elements. constexpr real_type real() const noexcept requires (vec_complex) { const auto e = simd_bit_cast(*this); return permute(e, [](simd_size_type idx) { return idx * 2; }); }; - /// @brief Return a vec containing only the imaginary values from this complex object. - /// @return A new basic_vec with the same number of elements as the original object but containing only the imaginary components. - /// @ingroup simd_complex + /// @brief Return the imaginary components of the complex elements. + /// @return A real-valued vector with the same number of elements. constexpr real_type imag() const noexcept requires (vec_complex) { const auto e = simd_bit_cast(*this); return permute(e, [](simd_size_type idx) { return idx * 2 + 1; }); }; - /// @brief Set the real part of every complex basic_vec element from the respective element of the supplied real values. - /// @param new_reals The basic_vec value of real components to insert into this object. - /// @ingroup simd_complex + /// @brief Replace the real component of each complex element. + /// @param new_reals The vector supplying the new real components. constexpr void real(const real_type& new_reals) noexcept requires detail::complex_number<_Tp> { *this = basic_vec(new_reals, imag()); } - /// @brief Set the imaginary part of every complex basic_vec element from the respective element of the supplied imaginary values. - /// @param new_imags The basic_vec value of imaginary components to insert into this object. - /// @ingroup simd_complex + /// @brief Replace the imaginary component of each complex element. + /// @param new_imags The vector supplying the new imaginary components. constexpr void imag(const real_type& new_imags) noexcept requires detail::complex_number<_Tp> { *this = basic_vec(real(), new_imags); } + /// @} cpp26_complex_access + #ifdef _XVEC_DEFINE_OUTPUT_OPERATORS /// Output the contents of the simd::vec vector to a standard stream, /// element-by-element. - /// \ingroup simd_stream_output + /// @ingroup xvec_stream_output friend std::ostream &operator<<(std::ostream& stream, basic_vec value) { // Note that the values are printed in reverse order to match dvec. for (simd_size_type i = 0; i < basic_vec::size; ++i) { @@ -520,7 +642,10 @@ public: #endif // _XVEC_DEFINE_OUTPUT_OPERATORS }; -/// A simd-generic version of simd_bit_cast which direct invokes std::bit_cast. +/// @addtogroup xvec_unclassified +/// @{ + +/// A simd-generic version of simd_bit_cast which directly invokes std::bit_cast. template constexpr auto simd_bit_cast(const _From& v) noexcept { return std::bit_cast<_To>(v); } @@ -550,9 +675,12 @@ auto simd_bit_cast(const _From& v) noexcept return new_type{__builtin_bit_cast(typename new_type::builtin_type, v.to_builtin())}; } +/// @} xvec_unclassified + /// Deduction guide from static extent. Anything span-like, with a compile-time /// size which is small enough to fit a vec, and with valid element types can /// be turned into a vec. +/// @ingroup cpp26_ctor template requires (detail::span_extent_v> <= detail::max_fixed_size>>) diff --git a/include/xvec/x86/intrin.hpp b/include/xvec/x86/intrin.hpp index 198f8e0..a6bc50b 100644 --- a/include/xvec/x86/intrin.hpp +++ b/include/xvec/x86/intrin.hpp @@ -18,29 +18,47 @@ namespace _XVEC_NAMESPACE::simd::x86 { -/// Concepts for detecting vectors which fit into specific sizes of registers. -///@{ +/** + * @defgroup x86_intrin x86 intrinsic interfaces + * @brief Register-size concepts and SIMD wrappers for x86-specific operations. + * @{ + */ + +/// @brief Detect a vector occupying at most an xmm-sized register. +/// @tparam _Vec The vector type. +/// @tparam _Tp The required element type. template concept xmm_register = (sizeof(_Vec) <= 16) && (std::same_as<_Tp, typename _Vec::value_type>); +/// @brief Detect a vector larger than xmm and no larger than ymm. +/// @tparam _Vec The vector type. +/// @tparam _Tp The required element type. template concept ymm_register = (sizeof(_Vec) > 16 && sizeof(_Vec) <= 32) && (std::same_as<_Tp, typename _Vec::value_type>); +/// @brief Detect a vector larger than ymm and no larger than zmm. +/// @tparam _Vec The vector type. +/// @tparam _Tp The required element type. template concept zmm_register = (sizeof(_Vec) > 32 && sizeof(_Vec) <= 64) && (std::same_as<_Tp, typename _Vec::value_type>); -///@} #if defined(__GFNI__) /// Compute an affine transformation in the Galois Field 2^8. An affine /// transformation is defined by A * x + b, where A represents an 8 by 8 bit /// matrix, x represents an 8-bit vector, and b is a constant immediate byte. - +/// /// This function call wraps a call directly to the underlying GFNI instruction /// using 64-bit elements throughout. It allows the underlying GFNI instruction /// to be used in any way that the hardware supports. It requires 8 bytes to be /// supplied for every 8x8 matrix element. It allows arbitrary numbers of /// byte/matrix groups, and will call the intrinsic as many times as needed for /// all the groups. +/// @tparam imm_byte The constant byte added by the affine transformation. +/// @tparam _Bytes The vector type containing byte elements. +/// @tparam _Matrix The vector type containing 64-bit matrix elements. +/// @param b The input byte elements. +/// @param m The matrix elements. +/// @return The transformed byte elements. template requires ((sizeof(typename _Bytes::value_type) == 1) && (sizeof(typename _Matrix::value_type) == 8) && @@ -67,6 +85,11 @@ inline _Bytes gf2p8affine(const _Bytes& b, const _Matrix& m) /// This variant of the GFNI affine instruction provides an easy way of /// accessing the most common use case, where every input byte element is /// multiplied by a single 8x8 bit matrix. +/// @tparam imm_byte The constant byte added by the affine transformation. +/// @tparam _Bytes The vector type containing byte elements. +/// @param b The input byte elements. +/// @param m The shared matrix. +/// @return The transformed byte elements. template requires (sizeof(typename _Bytes::value_type) == 1) // Allow any type of single byte element to be transformed. inline _Bytes gf2p8affine(const _Bytes& b, uint64_t m) @@ -81,6 +104,8 @@ inline _Bytes gf2p8affine(const _Bytes& b, uint64_t m) inline auto gf2p8affine(auto unhandled, auto); // Does nothing for other platforms to allow link-time detection. #endif +/// @} x86_intrin + } // End of simd::x86 namespace namespace _XVEC_NAMESPACE::simd::detail { diff --git a/include/xvec/x86/permute.hpp b/include/xvec/x86/permute.hpp index 99f6e12..85b01c0 100644 --- a/include/xvec/x86/permute.hpp +++ b/include/xvec/x86/permute.hpp @@ -129,8 +129,8 @@ _mm512_permutex2var_epi8_emulated(__m512i v_data_0, // for that permutation comes from the upper 5-bits of the incoming index (i.e., discard the LSB). The permute // instruction masks the index bits itself, so we only need to put the upper 5-bits of the index // into the correct location. - __v32hi evenPerm = _mm512_permutex2var_epi16(v_data_0, v_shuf_idxs >> 1, v_data_1); - __v32hi oddPerm = _mm512_permutex2var_epi16(v_data_0, v_shuf_idxs >> 9, v_data_1); + auto evenPerm = _mm512_permutex2var_epi16(v_data_0, v_shuf_idxs >> 1, v_data_1); + auto oddPerm = _mm512_permutex2var_epi16(v_data_0, v_shuf_idxs >> 9, v_data_1); // evenPerm and oddPerm now contain pairs of bytes. We need to select which byte of each pair to use, // and that selection is driven by the LSB of each index (i.e., LSB == 0 means use the lower byte of the diff --git a/include/xvec/x86/x86_impl.hpp b/include/xvec/x86/x86_impl.hpp index ed6b7c3..ff0ea3e 100644 --- a/include/xvec/x86/x86_impl.hpp +++ b/include/xvec/x86/x86_impl.hpp @@ -1577,12 +1577,13 @@ constexpr basic_vec<_Tp, _Abi> sqrt(x86_sse_tag, const basic_vec<_Tp, _Abi>& v) return chunked_invoke([=](auto v) { return decltype(v)(impl(v)); }, v); } -/// @brief Compute the saturated addition of each respective pair of SIMD elements -/// @ingroup simd_numeric +/// @brief Compute the saturated addition of each respective pair of vector elements. +/// @internal /// @tparam _Tp The integral type of each basic_vec element. -/// @tparam _Abi The ABI of the basic_vec -/// @param v The basic_vec value -/// @return A basic_vec value in which each element is the saturating addition of the respective input basic_vec elements. +/// @tparam _Abi The ABI of the basic_vec. +/// @param lhs The first basic_vec value. +/// @param rhs The second basic_vec value. +/// @return A basic_vec containing the element-wise saturated sums. template requires (sizeof(_Tp) <= 2) // x86 only has support for 8 and 16-bit saturating operations. Defer everything else to the // generic synthesised version. @@ -1622,12 +1623,13 @@ constexpr basic_vec<_Tp, _Abi> saturating_add(x86_tag, const basic_vec<_Tp, _Abi return chunked_invoke(wrapper, lhs, rhs); } -/// @brief Compute the saturated subtraction of each respective pair of SIMD elements -/// @ingroup simd_numeric +/// @brief Compute the saturated subtraction of each respective pair of vector elements. +/// @internal /// @tparam _Tp The integral type of each basic_vec element. -/// @tparam _Abi The ABI of the basic_vec -/// @param v The basic_vec value -/// @return A basic_vec value in which each element is the saturating subtraction of the respective input basic_vec elements. +/// @tparam _Abi The ABI of the basic_vec. +/// @param lhs The first basic_vec value. +/// @param rhs The second basic_vec value. +/// @return A basic_vec containing the element-wise saturated differences. template requires (sizeof(_Tp) <= 2) // x86 only has support for 8 and 16-bit saturating operations. Defer everything else to the // generic synthesised version. diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 584202e..646f3f6 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -250,7 +250,6 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") xvec_test_common INTERFACE -Wno-unknown-pragmas - -flax-vector-conversions ) endif()