Clean up and fix issues in doc-check scripts
authorTeemu Murtola <teemu.murtola@gmail.com>
Thu, 3 Apr 2014 03:16:52 +0000 (06:16 +0300)
committerGerrit Code Review <gerrit@gerrit.gromacs.org>
Thu, 10 Apr 2014 14:03:00 +0000 (16:03 +0200)
- Some 'documentation' -> 'doc' replacements in method names to make
  lines shorter and to make method names more consistent.
- Make the checker work for members of anonymous namespaces.
- To achieve the above, add minimal modeling of namespaces and members
  to gmxtree.py, and model the parent compounds of members better in
  doxygenxml.py.
- Make the checker check also documentation that is ignored by Doxygen.
  This is now possible when anonymouns namespaces work.
  --check-ignored now only controls whether the ignored comments provoke
  a note or not.  This is not enabled currently, because it produces
  quite a lot of noise.
- Fix documentation issues in those ignored Doxygen comments (all the
  source code changes).
- Encapsulate some logic in gmxtree.py related to how the API type is
  handled in the case of legacy (undocumented) modules.  This simplifies
  the graph generation logic, and replaces a lot of the "legacy" edges
  with more descriptive edges: installed headers in legacy modules are
  now treated as public API headers.
- Add a basic legend to the module graph.

Change-Id: Ia4e83468548b361f37bdb8d35862e636d7abddd6

13 files changed:
doxygen/doxygen-check.py
doxygen/doxygenxml.py
doxygen/gmxtree.py
doxygen/graphbuilder.py
src/gromacs/gmxlib/cinvsqrtdata.c
src/gromacs/legacyheaders/gmx_omp_nthreads.h
src/gromacs/legacyheaders/nbnxn_cuda_data_mgmt.h
src/gromacs/legacyheaders/pmalloc_cuda.h
src/gromacs/legacyheaders/types/nb_verlet.h
src/gromacs/math/utilities.h
src/gromacs/mdlib/nbnxn_cuda/nbnxn_cuda.h
src/gromacs/random/random.h
src/gromacs/timing/walltime_accounting.h

index f292b85abedb06194a0934b8aee968dd7d9b491b..e2c30a59be5b3f12566c80a499c5db2d3f872f0d 100755 (executable)
@@ -68,7 +68,7 @@ def check_file(fileobj, reporter):
         # TODO: Add rule to exclude examples from this check
         if fileobj.is_installed():
             reporter.file_error(fileobj, "source file is installed")
-        if fileobj.get_documentation_type() != DocType.internal:
+        if fileobj.get_doc_type() != DocType.internal:
             reporter.file_error(fileobj,
                     "source file documentation appears outside full documentation")
         elif fileobj.get_api_type() != DocType.internal:
@@ -76,19 +76,19 @@ def check_file(fileobj, reporter):
     elif fileobj.is_test_file() and fileobj.is_installed():
         reporter.file_error(fileobj, "test file is installed")
     elif fileobj.is_installed():
-        if fileobj.get_documentation_type() != DocType.public:
+        if fileobj.get_doc_type() != DocType.public:
             reporter.file_error(fileobj,
                     "public header has non-public documentation")
-    elif fileobj.get_documentation_type() == DocType.public:
+    elif fileobj.get_doc_type() == DocType.public:
         reporter.file_error(fileobj,
                 "non-installed header has public documentation")
     elif fileobj.get_api_type() == DocType.public:
         reporter.file_error(fileobj,
                 "non-installed header specified as part of public API")
-    elif fileobj.get_documentation_type() < fileobj.get_api_type():
+    elif fileobj.get_doc_type() < fileobj.get_api_type():
         reporter.file_error(fileobj,
                 "API type ({0}) conflicts with documentation visibility ({1})"
-                .format(fileobj.get_api_type(), fileobj.get_documentation_type()))
+                .format(fileobj.get_api_type(), fileobj.get_doc_type()))
 
     if not fileobj.has_brief_description():
         reporter.file_error(fileobj,
@@ -132,14 +132,13 @@ def check_include(fileobj, includedfile, reporter):
         filemodule = fileobj.get_module()
         othermodule = otherfile.get_module()
         if fileobj.is_documented() and otherfile.is_documented():
-            filetype = fileobj.get_documentation_type()
-            othertype = otherfile.get_documentation_type()
+            filetype = fileobj.get_doc_type()
+            othertype = otherfile.get_doc_type()
             if filetype > othertype:
                 reporter.code_issue(includedfile,
                         "{0} file includes {1} file {2}"
                         .format(filetype, othertype, includedfile))
-        check_api = (othermodule and othermodule.is_documented() and
-                filemodule != othermodule)
+        check_api = (otherfile.api_type_is_reliable() and filemodule != othermodule)
         if check_api and otherfile.get_api_type() < DocType.library:
             reporter.code_issue(includedfile,
                     "included file {0} is not documented as exposed outside its module"
@@ -156,8 +155,8 @@ def check_class(classobj, reporter):
     """Check documentation for a class/struct/union."""
     check_entity(classobj, reporter)
     if classobj.is_documented():
-        classtype = classobj.get_documentation_type()
-        filetype = classobj.get_file_documentation_type()
+        classtype = classobj.get_doc_type()
+        filetype = classobj.get_file_doc_type()
         if classtype == DocType.public and not classobj.is_in_installed_file():
             reporter.doc_error(classobj,
                     "has public documentation, but is not in installed header")
@@ -166,12 +165,11 @@ def check_class(classobj, reporter):
                     "is in {0} file(s), but appears in {1} documentation"
                     .format(filetype, classtype))
 
-def check_member(member, reporter):
+def check_member(member, reporter, check_ignored):
     """Check documentation for a generic member."""
     check_entity(member, reporter)
     if member.is_documented():
-        if not member.is_visible():
-            # TODO: This is triggered by members in anonymous namespaces.
+        if check_ignored and not member.is_visible():
             reporter.doc_note(member,
                     "is documented, but is ignored by Doxygen, because its scope is not documented")
         if member.has_inbody_description():
@@ -191,7 +189,7 @@ def main():
     parser.add_option('--ignore',
                       help='Set file with patterns for messages to ignore')
     parser.add_option('--check-ignored', action='store_true',
-                      help='Check documentation ignored by Doxygen')
+                      help='Issue notes for comments ignored by Doxygen')
     parser.add_option('-q', '--quiet', action='store_true',
                       help='Do not write status messages')
     options, args = parser.parse_args()
@@ -231,8 +229,7 @@ def main():
         check_class(classobj, reporter)
 
     for memberobj in tree.get_members():
-        if memberobj.is_visible() or options.check_ignored:
-            check_member(memberobj, reporter)
+        check_member(memberobj, reporter, options.check_ignored)
 
     reporter.write_pending()
     reporter.report_unused_filters()
index f26ad9cdbdf6102913fd8bed6760aefc60a9f120..49de76261c8bf72c27930099ecbd9499dbfd97b3 100755 (executable)
@@ -370,6 +370,10 @@ class Member(Entity):
     def __init__(self, name, refid):
         Entity.__init__(self, name, refid)
         self._parents = set()
+        self._class = None
+        self._namespace = None
+        self._files = set()
+        self._group = None
         self._location = None
         self._alternates = set()
         self._loaded = False
@@ -379,38 +383,31 @@ class Member(Entity):
     def add_parent_compound(self, compound):
         """Add a compound that contains this member."""
         self._parents.add(compound)
+        if isinstance(compound, Class):
+            assert self._class is None
+            self._class = compound
+        elif isinstance(compound, Namespace):
+            assert self._namespace is None
+            self._namespace = compound
+        elif isinstance(compound, File):
+            self._files.add(compound)
+        elif isinstance(compound, Group):
+            assert self._group is None
+            self._group = compound
+        else:
+            assert False
 
-    def _get_raw_location(self):
-        """Returns the BodyLocation object associated with this member.
+    def merge_definition(self, definition):
+        """Merge another member into this.
 
-        This is necessary so that EnumValue can override it report a non-empty
-        location: Doxygen doesn't provide any location for <enumvalue>.
+        See DocumentationSet.merge_duplicates().
         """
-        return self._location
-
-    def get_parent_compounds(self):
-        return self._parents
-
-    def get_inherited_visibility(self):
-        return max([parent.get_visibility() for parent in self._parents])
-
-    def is_visible(self):
-        return self.get_inherited_visibility() != DocType.none
-
-    def has_same_body_location(self):
-        return self._get_raw_location().has_same_body_location()
-
-    def get_reporter_location(self):
-        return self._get_raw_location().get_reporter_location()
-
-    def get_location(self):
-        return self._get_raw_location().get_location()
-
-    def get_body_location(self):
-        return self._get_raw_location().get_body_location()
-
-    def merge_definition(self, definition):
+        assert self._class is None
+        assert definition._class is None
+        assert self._group == definition._group
+        assert self._namespace == definition._namespace
         self._parents.update(definition._parents)
+        self._files.update(definition._files)
         self._alternates.add(definition)
 
     def load_details_from_element(self, rootelem, xmlpath):
@@ -465,8 +462,50 @@ class Member(Entity):
         """
         return False
 
+    def _get_raw_location(self):
+        """Returns the BodyLocation object associated with this member.
+
+        This is necessary so that EnumValue can override it report a non-empty
+        location: Doxygen doesn't provide any location for <enumvalue>.
+        """
+        return self._location
+
+    def get_reporter_location(self):
+        return self._get_raw_location().get_reporter_location()
+
+    def get_location(self):
+        """Return main location for the member.
+
+        This typically corresponds to the declaration.
+        """
+        return self._get_raw_location().get_location()
+
+    def get_body_location(self):
+        """Return location of the body for the member.
+
+        Some types of members do not have a body location, in which case this
+        returns None.
+        """
+        return self._get_raw_location().get_body_location()
+
+    def has_same_body_location(self):
+        """Check whether the main location is the same as body location."""
+        return self._get_raw_location().has_same_body_location()
+
+    def get_namespace(self):
+        return self._namespace
+
+    def get_parent_compounds(self):
+        return self._parents
+
+    def get_inherited_visibility(self):
+        return max([parent.get_visibility() for parent in self._parents])
+
     def show(self):
         self.show_base()
+        if self._alternates:
+            idlist = [x.get_id() for x in self._alternates]
+            print 'Alt. IDs:   {0}'.format(', '.join(idlist))
         print 'Parent vis: {0}'.format(self.get_inherited_visibility())
         print 'Location:   {0}'.format(self.get_location().get_full_string())
         print 'Body loc:   {0}'.format(self.get_body_location().get_full_string())
@@ -539,6 +578,7 @@ class Compound(Entity):
     contains references to contained compounds, and details of all members
     within the compound.
     """
+
     def __init__(self, name, refid):
         Entity.__init__(self, name, refid)
         self._members = dict()
@@ -891,6 +931,9 @@ class Namespace(Compound):
     def get_reporter_location(self):
         return self._doclocation.get_reporter_location()
 
+    def is_anonymous(self):
+        return 'anonymous_namespace{' in self.get_name()
+
     def show(self):
         self.show_base()
         print 'Doc. loc.: {0}'.format(self._doclocation.get_full_string())
@@ -1093,9 +1136,9 @@ class DocumentationSet(object):
     def merge_duplicates(self):
         """Merge duplicate member definitions based on body location.
 
-        At least for functions that are declared in a header, but have their
-        body in a source file, Doxygen seems to create two different IDs, but
-        the contents of the members are the same, except for the location
+        At least for some functions that are declared in a header, but have
+        their body in a source file, Doxygen seems to create two different IDs,
+        but the contents of the members are the same, except for the location
         attribute.  This method merges members that have identical name and
         body location into a single member that keeps the information from both
         instances (they should only differ in the location attribute and in
@@ -1190,8 +1233,11 @@ class DocumentationSet(object):
     def get_groups(self, name):
         return self.get_compounds(Group, lambda x: x.get_name() in name)
 
-    def get_namespaces(self, name):
-        return self.get_compounds(Namespace, lambda x: x.get_name() in name)
+    def get_namespaces(self, name=None):
+        if name:
+            return self.get_compounds(Namespace, lambda x: x.get_name() in name)
+        else:
+            return self.get_compounds(Namespace)
 
     def get_classes(self, name=None):
         if name:
index 6a8d602a244c3c1c17e5eb721978fed15f0ab5f8..e196da3d65a62b90598ac54a2bd5a2c5833dddb8 100644 (file)
@@ -196,7 +196,7 @@ class File(object):
     def get_name(self):
         return os.path.basename(self._abspath)
 
-    def get_documentation_type(self):
+    def get_doc_type(self):
         if not self._rawdoc:
             return DocType.none
         return self._rawdoc.get_visibility()
@@ -204,6 +204,22 @@ class File(object):
     def get_api_type(self):
         return self._apitype
 
+    def api_type_is_reliable(self):
+        if self._apitype > DocType.internal:
+            return True
+        module = self.get_module()
+        return module and module.is_documented()
+
+    def is_public(self):
+        if self.api_type_is_reliable():
+            return self.get_api_type() == DocType.public
+        return self.get_api_type() == DocType.public or self.is_installed()
+
+    def is_module_internal(self):
+        if self.is_source_file():
+            return True
+        return not self.is_installed() and self.get_api_type() <= DocType.internal
+
     def get_expected_module(self):
         return self._dir.get_module()
 
@@ -352,6 +368,15 @@ class Module(object):
     def get_group(self):
         return self._group
 
+class Namespace(object):
+
+    """Namespace in the GROMACS source code."""
+
+    def __init__(self, rawdoc):
+        self._rawdoc = rawdoc
+
+    def is_anonymous(self):
+        return self._rawdoc.is_anonymous()
 
 class Class(object):
 
@@ -376,19 +401,66 @@ class Class(object):
     def has_brief_description(self):
         return self._rawdoc.has_brief_description()
 
-    def get_documentation_type(self):
+    def get_doc_type(self):
+        """Return documentation type (visibility) for the class.
+
+        In addition to the actual code, this encodes GROMACS-specific logic
+        of setting EXTRACT_LOCAL_CLASSES=YES only for the full documentation.
+        Local classes never appear outside the full documentation, no matter
+        what is their visibility.
+        """
         if not self.is_documented():
             return DocType.none
         if self._rawdoc.is_local():
             return DocType.internal
         return self._rawdoc.get_visibility()
 
-    def get_file_documentation_type(self):
-        return max([fileobj.get_documentation_type() for fileobj in self._files])
+    def get_file_doc_type(self):
+        return max([fileobj.get_doc_type() for fileobj in self._files])
 
     def is_in_installed_file(self):
         return any([fileobj.is_installed() for fileobj in self._files])
 
+class Member(object):
+
+    """Member (in Doxygen terminology) in the GROMACS source tree.
+
+    Currently, modeling is limited to the minimal set of properties that the
+    checker uses.
+    """
+
+    def __init__(self, rawdoc, namespace):
+        self._rawdoc = rawdoc
+        self._namespace = namespace
+
+    def get_name(self):
+        return self._rawdoc.get_name()
+
+    def get_reporter_location(self):
+        return self._rawdoc.get_reporter_location()
+
+    def is_documented(self):
+        return self._rawdoc.is_documented()
+
+    def has_brief_description(self):
+        return self._rawdoc.has_brief_description()
+
+    def has_inbody_description(self):
+        return self._rawdoc.has_inbody_description()
+
+    def is_visible(self):
+        """Return whether the member is visible in Doxygen documentation.
+
+        Doxygen ignores members whose parent compounds are not documented.
+        However, when EXTRACT_ANON_NPACES=ON (which is set for our full
+        documentation), members of anonymous namespaces are extracted even if
+        the namespace is the only parent and is not documented.
+        """
+        if self._namespace and self._namespace.is_anonymous():
+            return True
+        return self._rawdoc.get_inherited_visibility() != DocType.none
+
+
 class GromacsTree(object):
 
     """Root object for navigating the GROMACS source tree.
@@ -423,6 +495,8 @@ class GromacsTree(object):
         self._files = dict()
         self._modules = dict()
         self._classes = set()
+        self._namespaces = set()
+        self._members = set()
         self._walk_dir(os.path.join(self._source_root, 'src'))
         rootdir = self._get_dir(os.path.join('src', 'gromacs'))
         for subdir in rootdir.get_subdirectories():
@@ -503,7 +577,9 @@ class GromacsTree(object):
         self._load_modules()
         self._load_files()
         if not only_files:
+            self._load_namespaces()
             self._load_classes()
+            self._load_members()
 
     def _load_dirs(self):
         """Load Doxygen XML directory information."""
@@ -568,6 +644,14 @@ class GromacsTree(object):
             fileobj.set_doc_xml(filedoc, self)
             self._docmap[filedoc] = fileobj
 
+    def _load_namespaces(self):
+        """Load Doxygen XML namespace information."""
+        nsdocs = self._docset.get_namespaces()
+        for nsdoc in nsdocs:
+            nsobj = Namespace(nsdoc)
+            self._docmap[nsdoc] = nsobj
+            self._namespaces.add(nsobj)
+
     def _load_classes(self):
         """Load Doxygen XML class information."""
         classdocs = self._docset.get_classes()
@@ -577,6 +661,16 @@ class GromacsTree(object):
             self._docmap[classdoc] = classobj
             self._classes.add(classobj)
 
+    def _load_members(self):
+        """Load Doxygen XML member information."""
+        memberdocs = self._docset.get_members()
+        for memberdoc in memberdocs:
+            nsdoc = memberdoc.get_namespace()
+            nsobj = self.get_object(nsdoc)
+            memberobj = Member(memberdoc, nsobj)
+            self._docmap[memberdoc] = memberobj
+            self._members.add(memberobj)
+
     def _get_dir(self, relpath):
         """Get directory object for a path relative to source tree root."""
         return self._dirs.get(relpath)
@@ -609,6 +703,8 @@ class GromacsTree(object):
 
     def get_object(self, docobj):
         """Get tree object for a Doxygen XML object."""
+        if docobj is None:
+            return None
         return self._docmap.get(docobj)
 
     def get_files(self):
@@ -625,5 +721,4 @@ class GromacsTree(object):
 
     def get_members(self):
         """Get iterable for all members (in Doxygen terms) in the source tree."""
-        # TODO: Add wrappers to solve some issues.
-        return self._docset.get_members()
+        return self._members
index 47f1f70be8ce9c08c429e9ac3cb03353c265ff69..f67d115cecd1c067e03f058364a7bbc5158eb603 100755 (executable)
@@ -343,10 +343,10 @@ class GraphBuilder(object):
         gmxtree.
         """
         intramodule = (fromfile.get_module() == tofile.get_module())
-        is_legacy = not tofile.get_module().is_documented()
+        is_legacy = not tofile.api_type_is_reliable()
         if fromfile.get_module() == tofile.get_module():
             edgetype = EdgeType.intramodule
-        elif tofile.get_api_type() == DocType.internal:
+        elif tofile.get_api_type() == DocType.internal and not tofile.is_public():
             if is_legacy:
                 edgetype = EdgeType.legacy
             else:
@@ -355,30 +355,30 @@ class GraphBuilder(object):
             edgetype = EdgeType.test
         elif tofile.is_test_file():
             edgetype = EdgeType.undocumented
-        elif fromfile.is_source_file() or \
-                (fromfile.get_api_type() <= DocType.internal and \
-                not fromfile.is_installed()):
-            if tofile.get_api_type() == DocType.public:
+        elif fromfile.is_module_internal():
+            if tofile.is_public():
                 edgetype = EdgeType.pubimpl
             elif tofile.get_api_type() == DocType.library:
                 edgetype = EdgeType.libimpl
-            elif is_legacy or not tofile.is_documented():
+            elif is_legacy:
                 edgetype = EdgeType.legacy
+            elif not tofile.is_documented():
+                edgetype = EdgeType.undocumented
             else:
                 raise ValueError('Unknown edge type between {0} and {1}'
-                        .format(fromfile.path, tofile.path))
+                        .format(fromfile.get_relpath(), tofile.get_relpath()))
         elif fromfile.get_api_type() == DocType.library:
             edgetype = EdgeType.library
-        elif fromfile.get_api_type() == DocType.public or fromfile.is_installed():
-            if tofile.get_api_type() == DocType.public or \
-                    tofile.get_documentation_type() == DocType.public or \
-                    (tofile.is_installed() and not tofile.is_documented()):
+        elif fromfile.is_public() or fromfile.is_installed():
+            if tofile.is_public() or tofile.is_installed():
                 edgetype = EdgeType.public
             else:
                 edgetype = EdgeType.undocumented
+        elif is_legacy:
+            edgetype = EdgeType.legacy
         else:
             raise ValueError('Unknown edge type between {0} and {1}'
-                    .format(fromfile.path, tofile.path))
+                    .format(fromfile.get_relpath(), tofile.get_relpath()))
         return Edge(filenodes[fromfile], filenodes[tofile], edgetype)
 
     def _create_file_edges(self, filenodes):
@@ -397,6 +397,17 @@ class GraphBuilder(object):
                     edges.append(edge)
         return edges
 
+    def _get_module_color(self, modulegroup):
+        if modulegroup == 'legacy':
+            return 'fillcolor=grey75'
+        elif modulegroup == 'analysismodules':
+            return 'fillcolor="0 .2 1"'
+        elif modulegroup == 'utilitymodules':
+            return 'fillcolor=".08 .2 1"'
+        elif modulegroup == 'mdrun':
+            return 'fillcolor=".75 .2 1"'
+        return None
+
     def _create_module_node(self, module, filenodes):
         """Create node for a module.
 
@@ -408,17 +419,12 @@ class GraphBuilder(object):
         properties.append('shape=ellipse')
         properties.append('URL="\\ref module_{0}"'.format(module.get_name()))
         if not module.is_documented():
+            fillcolor = self._get_module_color('legacy')
+        else:
+            fillcolor = self._get_module_color(module.get_group())
+        if fillcolor:
             style.append('filled')
-            properties.append('fillcolor=grey75')
-        elif module.get_group() == 'analysismodules':
-            style.append('filled')
-            properties.append('fillcolor="0 .2 1"')
-        elif module.get_group() == 'utilitymodules':
-            style.append('filled')
-            properties.append('fillcolor=".08 .2 1"')
-        elif module.get_group() == 'mdrun':
-            style.append('filled')
-            properties.append('fillcolor=".75 .2 1"')
+            properties.append(fillcolor)
         rootdir = module.get_root_dir()
         if rootdir.has_installed_files():
             properties.append('color=".66 .5 1"')
@@ -430,6 +436,20 @@ class GraphBuilder(object):
             node.add_child(self._create_file_node(childfile, filenodes))
         return node
 
+    def _create_legend_node(self, label, modulegroup):
+        if modulegroup:
+            nodename = 'legend_' + modulegroup
+            fillcolor = self._get_module_color(modulegroup)
+        else:
+            nodename = 'legend_' + label
+            fillcolor = None
+        style = []
+        properties = []
+        if fillcolor:
+            style.append('filled')
+            properties.append(fillcolor)
+        return Node(nodename, label, style, properties)
+
     def create_modules_graph(self):
         """Create module dependency graph."""
         filenodes = dict()
@@ -445,6 +465,15 @@ class GraphBuilder(object):
                 nodes.append(node)
             modulenodes.append(node)
         edges = self._create_file_edges(filenodes)
+        # TODO: Consider adding invisible edges to order the nodes better.
+        # TODO: Consider adding legend for the edge types as well.
+        legendnode = Node('legend', 'legend')
+        legendnode.add_child(self._create_legend_node('legacy', 'legacy'))
+        legendnode.add_child(self._create_legend_node('analysis', 'analysismodules'))
+        legendnode.add_child(self._create_legend_node('utility', 'utilitymodules'))
+        legendnode.add_child(self._create_legend_node('mdrun', 'mdrun'))
+        legendnode.add_child(Node('legend_installed', 'installed', properties=['color=".66 .5 1"', 'penwidth=3']))
+        nodes.append(legendnode)
         graph = Graph(nodes, edges)
         for node in modulenodes:
             graph.collapse_node(node)
index 77ca8d35720972a0c37f11ead5277cf3423ffbd5..429764eecc47814f0eba188ae28f9f9f9ee33cf0 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -42,8 +42,8 @@
 
 struct gmx_invsqrtdata
 {
-    unsigned int    exptab[256];    /*!< Exponential lookup table */
-    unsigned int    fracttab[4096]; /*!< Mantissa lookup table    */
+    unsigned int    exptab[256];    /**< Exponential lookup table */
+    unsigned int    fracttab[4096]; /**< Mantissa lookup table    */
 };
 
 
index f4010010dba270082c377b2786c52645cb7a256b..4c30d7e7d268a0d2c69d202edf6454c1142b1ecc 100644 (file)
@@ -33,8 +33,8 @@
  * the research papers on the package. Check out http://www.gromacs.org.
  */
 
-#ifndef GMX_OMP_NTHREADS
-#define GMX_OMP_NTHREADS
+#ifndef GMX_OMP_NTHREADS_H
+#define GMX_OMP_NTHREADS_H
 
 #include <stdio.h>
 #include "typedefs.h"
@@ -46,7 +46,7 @@ extern "C" {
 }
 #endif
 
-/*! Enum values corresponding to multithreaded algorithmic modules. */
+/** Enum values corresponding to multithreaded algorithmic modules. */
 typedef enum module_nth
 {
     /* Default is meant to be used in OMP regions outside the named
@@ -56,9 +56,12 @@ typedef enum module_nth
     emntNR
 } module_nth_t;
 
-/*! Initializes the per-module thread count. It is compatible with tMPI,
- *  thread-safety is ensured (for the features available with tMPI).
- *  This function should caled only once during the initialization of mdrun. */
+/*! \brief
+ * Initializes the per-module thread count.
+ *
+ * It is compatible with tMPI, thread-safety is ensured (for the features
+ * available with tMPI).
+ * This function should caled only once during the initialization of mdrun. */
 void gmx_omp_nthreads_init(FILE *fplog, t_commrec *cr,
                            int nthreads_hw_avail,
                            int omp_nthreads_req,
@@ -66,14 +69,18 @@ void gmx_omp_nthreads_init(FILE *fplog, t_commrec *cr,
                            gmx_bool bCurrNodePMEOnly,
                            gmx_bool bFullOmpSupport);
 
-/*! Returns the number of threads to be used in the given module m. */
+/*! \brief
+ * Returns the number of threads to be used in the given module \p mod. */
 int gmx_omp_nthreads_get(int mod);
 
-/*! \brief Sets the number of threads to be used in module. Intended
- *  for use in testing. */
+/*! \brief Sets the number of threads to be used in module.
+ *
+ * Intended for use in testing. */
 void gmx_omp_nthreads_set(int mod, int nthreads);
 
-/*! Read the OMP_NUM_THREADS env. var. and check against the value set on the command line. */
+/*! \brief
+ * Read the OMP_NUM_THREADS env. var. and check against the value set on the
+ * command line. */
 void gmx_omp_nthreads_read_env(int     *nthreads_omp,
                                gmx_bool bIsSimMaster);
 
@@ -84,4 +91,4 @@ void gmx_omp_nthreads_read_env(int     *nthreads_omp,
 }
 #endif
 
-#endif /* GMX_OMP_NTHREADS */
+#endif
index 62cdfe6ceab333a31b9d2aed1c067c769b5adb99..919e1355b09e20534dbadda4835cff8921ca1ca8 100644 (file)
@@ -54,7 +54,7 @@
 extern "C" {
 #endif
 
-/*! Initializes the data structures related to CUDA nonbonded calculations. */
+/** Initializes the data structures related to CUDA nonbonded calculations. */
 FUNC_QUALIFIER
 void nbnxn_cuda_init(FILE gmx_unused                 *fplog,
                      nbnxn_cuda_ptr_t gmx_unused     *p_cu_nb,
@@ -64,19 +64,19 @@ void nbnxn_cuda_init(FILE gmx_unused                 *fplog,
                      /* true of both local and non-local are don on GPU */
                      gmx_bool gmx_unused              bLocalAndNonlocal) FUNC_TERM
 
-/*! Initializes simulation constant data. */
+/** Initializes simulation constant data. */
 FUNC_QUALIFIER
 void nbnxn_cuda_init_const(nbnxn_cuda_ptr_t               gmx_unused  cu_nb,
                            const interaction_const_t      gmx_unused *ic,
                            const nonbonded_verlet_group_t gmx_unused *nbv_group) FUNC_TERM
 
-/*! Initializes pair-list data for GPU, called at every pair search step. */
+/** Initializes pair-list data for GPU, called at every pair search step. */
 FUNC_QUALIFIER
 void nbnxn_cuda_init_pairlist(nbnxn_cuda_ptr_t       gmx_unused  cu_nb,
                               const nbnxn_pairlist_t gmx_unused *h_nblist,
                               int                    gmx_unused  iloc) FUNC_TERM
 
-/*! Initializes atom-data on the GPU, called at every pair search step. */
+/** Initializes atom-data on the GPU, called at every pair search step. */
 FUNC_QUALIFIER
 void nbnxn_cuda_init_atomdata(nbnxn_cuda_ptr_t       gmx_unused  cu_nb,
                               const nbnxn_atomdata_t gmx_unused *atomdata) FUNC_TERM
@@ -86,21 +86,21 @@ FUNC_QUALIFIER
 void nbnxn_cuda_pme_loadbal_update_param(nbnxn_cuda_ptr_t          gmx_unused  cu_nb,
                                          const interaction_const_t gmx_unused *ic) FUNC_TERM
 
-/*! Uploads shift vector to the GPU if the box is dynamic (otherwise just returns). */
+/** Uploads shift vector to the GPU if the box is dynamic (otherwise just returns). */
 FUNC_QUALIFIER
 void nbnxn_cuda_upload_shiftvec(nbnxn_cuda_ptr_t       gmx_unused  cu_nb,
                                 const nbnxn_atomdata_t gmx_unused *nbatom) FUNC_TERM
 
-/*! Clears GPU outputs: nonbonded force, shift force and energy. */
+/** Clears GPU outputs: nonbonded force, shift force and energy. */
 FUNC_QUALIFIER
 void nbnxn_cuda_clear_outputs(nbnxn_cuda_ptr_t gmx_unused cu_nb,
                               int              gmx_unused flags) FUNC_TERM
 
-/*! Frees all GPU resources used for the nonbonded calculations. */
+/** Frees all GPU resources used for the nonbonded calculations. */
 FUNC_QUALIFIER
 void nbnxn_cuda_free(nbnxn_cuda_ptr_t gmx_unused  cu_nb) FUNC_TERM
 
-/*! Returns the GPU timings structure or NULL if GPU is not used or timing is off. */
+/** Returns the GPU timings structure or NULL if GPU is not used or timing is off. */
 FUNC_QUALIFIER
 wallclock_gpu_t * nbnxn_cuda_get_timings(nbnxn_cuda_ptr_t gmx_unused cu_nb)
 #ifdef GMX_GPU
@@ -111,12 +111,12 @@ wallclock_gpu_t * nbnxn_cuda_get_timings(nbnxn_cuda_ptr_t gmx_unused cu_nb)
 }
 #endif
 
-/*! Resets nonbonded GPU timings. */
+/** Resets nonbonded GPU timings. */
 FUNC_QUALIFIER
 void nbnxn_cuda_reset_timings(nbnxn_cuda_ptr_t gmx_unused cu_nb) FUNC_TERM
 
-/*! Calculates the minimum size of proximity lists to improve SM load balance
   with CUDA non-bonded kernels. */
+/** Calculates the minimum size of proximity lists to improve SM load balance
*  with CUDA non-bonded kernels. */
 FUNC_QUALIFIER
 int nbnxn_cuda_min_ci_balanced(nbnxn_cuda_ptr_t gmx_unused cu_nb)
 #ifdef GMX_GPU
@@ -127,7 +127,7 @@ int nbnxn_cuda_min_ci_balanced(nbnxn_cuda_ptr_t gmx_unused cu_nb)
 }
 #endif
 
-/*! Returns if analytical Ewald CUDA kernels are used. */
+/** Returns if analytical Ewald CUDA kernels are used. */
 FUNC_QUALIFIER
 gmx_bool nbnxn_cuda_is_kernel_ewald_analytical(const nbnxn_cuda_ptr_t gmx_unused cu_nb)
 #ifdef GMX_GPU
index d00179a4ad11f46e552df6ab96084e639c8d1906..2f620af8da73a55183a5c5761b69378895a963e0 100644 (file)
 extern "C" {
 #endif
 
-/*! Allocates nbytes of page-locked memory. */
+/** Allocates nbytes of page-locked memory. */
 void pmalloc(void gmx_unused **h_ptr, size_t gmx_unused nbytes) FUNC_TERM
 
-/*! Allocates nbytes of page-locked memory with write-combining. */
+/** Allocates nbytes of page-locked memory with write-combining. */
 void pmalloc_wc(void gmx_unused **h_ptr, size_t gmx_unused nbytes) FUNC_TERM
 
-/*! Frees page locked memory allocated with pmalloc. */
+/** Frees page locked memory allocated with pmalloc. */
 void pfree(void gmx_unused *h_ptr) FUNC_TERM
 
 #ifdef __cplusplus
index aaeeaa8b3616d2603c4e84dd64d90cdc96e5632a..e1e8ab0ca82bcc8b85469e79686039191c4b6262 100644 (file)
@@ -44,7 +44,7 @@ extern "C" {
 #endif
 
 
-/*! Nonbonded NxN kernel types: plain C, CPU SIMD, GPU CUDA, GPU emulation */
+/** Nonbonded NxN kernel types: plain C, CPU SIMD, GPU CUDA, GPU emulation */
 typedef enum
 {
     nbnxnkNotSet = 0,
@@ -56,7 +56,7 @@ typedef enum
     nbnxnkNR
 } nbnxn_kernel_type;
 
-/*! Return a string indentifying the kernel type */
+/** Return a string indentifying the kernel type */
 const char *lookup_nbnxn_kernel_name(int kernel_type);
 
 enum {
index c6db48d9a3759fc0926da3b9b443524004bec769..12601d4ead2af6726e3eed033722b280a9591169 100644 (file)
@@ -144,9 +144,9 @@ gmx_numzero(double a);
 unsigned int
 gmx_log2i(unsigned int x);
 
-/*! /brief Multiply two large ints
+/*! \brief Multiply two large ints
  *
- *  \return False iff overflow occured
+ * \return False iff overflow occured
  */
 gmx_bool
 check_int_multiply_for_overflow(gmx_int64_t  a,
index 994738f627a94ba99c359e15041b37d702fdfb89..c1945b58ef7ad20df6db35bb88380021304b1b07 100644 (file)
@@ -53,7 +53,9 @@
 extern "C" {
 #endif
 
-/*! Launch asynchronously the nonbonded force calculations.
+/*! \brief
+ * Launch asynchronously the nonbonded force calculations.
+ *
  *  This consists of the following (async) steps launched:
  *  - upload x and q;
  *  - upload shift vector;
@@ -66,16 +68,18 @@ void nbnxn_cuda_launch_kernel(nbnxn_cuda_ptr_t       gmx_unused  cu_nb,
                               int                    gmx_unused  flags,
                               int                    gmx_unused  iloc) FUNC_TERM
 
-/*! Launch asynchronously the download of nonbonded forces from the GPU
- *  (and energies/shift forces if required).
+/*! \brief
+ * Launch asynchronously the download of nonbonded forces from the GPU
+ * (and energies/shift forces if required).
  */
 void nbnxn_cuda_launch_cpyback(nbnxn_cuda_ptr_t       gmx_unused  cu_nb,
                                const nbnxn_atomdata_t gmx_unused *nbatom,
                                int                    gmx_unused  flags,
                                int                    gmx_unused  aloc) FUNC_TERM
 
-/*! Wait for the asynchronously launched nonbonded calculations and data
- *  transfers to finish.
+/*! \brief
+ * Wait for the asynchronously launched nonbonded calculations and data
+ * transfers to finish.
  */
 void nbnxn_cuda_wait_gpu(nbnxn_cuda_ptr_t       gmx_unused  cu_nb,
                          const nbnxn_atomdata_t gmx_unused *nbatom,
index e1a938b3fd6a39c7a813a44841a916056dfcb130..0fa41c0c308cfe732e8833c266d7eb991f1595b4 100644 (file)
@@ -46,12 +46,12 @@ extern "C" {
 #endif
 
 /*! Fixed random number seeds for different types of RNG */
-#define RND_SEED_UPDATE    1 /*!< For coordinate update (sd, bd, ..) */
-#define RND_SEED_REPLEX    2 /*!< For replica exchange */
-#define RND_SEED_VRESCALE  3 /*!< For V-rescale thermostat */
-#define RND_SEED_ANDERSEN  4 /*!< For Andersen thermostat */
-#define RND_SEED_TPI       5 /*!< For test particle insertion */
-#define RND_SEED_EXPANDED  6 /*!< For expanded emseble methods */
+#define RND_SEED_UPDATE    1 /**< For coordinate update (sd, bd, ..) */
+#define RND_SEED_REPLEX    2 /**< For replica exchange */
+#define RND_SEED_VRESCALE  3 /**< For V-rescale thermostat */
+#define RND_SEED_ANDERSEN  4 /**< For Andersen thermostat */
+#define RND_SEED_TPI       5 /**< For test particle insertion */
+#define RND_SEED_EXPANDED  6 /**< For expanded emseble methods */
 
 /*! \brief Abstract datatype for a random number generator
  *
index 8ed947eb8fa10c5610c209e2ecba3ffdef9e469f..b80d138d8f724cc45de4ad059a20ab899a2e02ad 100644 (file)
@@ -48,8 +48,9 @@ extern "C" {
 }
 #endif
 
-/*! Contains per-process and per-thread data about elapsed wall-clock
- *  times and integration steps performed. */
+/*! \brief
+ * Contains per-process and per-thread data about elapsed wall-clock
+ * times and integration steps performed. */
 typedef struct gmx_walltime_accounting *gmx_walltime_accounting_t;
 
 //! Constructor
@@ -60,18 +61,21 @@ walltime_accounting_init(int numOpenMPThreads);
 void
 walltime_accounting_destroy(gmx_walltime_accounting_t walltime_accounting);
 
-/*! Record initial time stamps, e.g. at run end or counter
- * re-initalization time */
+/*! \brief
+ * Record initial time stamps, e.g. at run end or counter re-initalization time
+ */
 void
 walltime_accounting_start(gmx_walltime_accounting_t walltime_accounting);
 
-/*! Measure and cache the elapsed wall-clock time since
- * walltime_accounting_start */
+/*! \brief
+ * Measure and cache the elapsed wall-clock time since
+ * walltime_accounting_start() */
 void
 walltime_accounting_end(gmx_walltime_accounting_t walltime_accounting);
 
-/*! Measure and return the elapsed wall-clock time since
- * walltime_accounting_start */
+/*! \brief
+ * Measure and return the elapsed wall-clock time since
+ * walltime_accounting_start() */
 double
 walltime_accounting_get_current_elapsed_time(gmx_walltime_accounting_t walltime_accounting);
 
@@ -91,15 +95,16 @@ walltime_accounting_get_start_time_stamp(gmx_walltime_accounting_t walltime_acco
 double
 walltime_accounting_get_nsteps_done(gmx_walltime_accounting_t walltime_accounting);
 
-/*! Set the number of integration steps done
+/*! \brief Set the number of integration steps done
  *
  * TODO consider whether this should get done in walltime_accounting_end */
 void
 walltime_accounting_set_nsteps_done(gmx_walltime_accounting_t   walltime_accounting,
                                     gmx_int64_t                 nsteps_done);
 
-/*! \brief Calls system timing routines (e.g. clock_gettime) to get the
- * (fractional) number of seconds elapsed since the epoch.
+/*! \brief
+ * Calls system timing routines (e.g. clock_gettime) to get the (fractional)
+ * number of seconds elapsed since the epoch.
  *
  * Resolution is implementation-dependent, but typically nanoseconds
  * or microseconds. */