1 /*
2  *  Copyright (C) 2004-2021 Edward F. Valeev
3  *
4  *  This file is part of Libint.
5  *
6  *  Libint is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU Lesser General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  Libint is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public License
17  *  along with Libint.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #ifndef _libint2_src_lib_libint_initialize_h_
22 #define _libint2_src_lib_libint_initialize_h_
23 
24 #include <libint2/util/cxxstd.h>
25 #if LIBINT2_CPLUSPLUS_STD < 2011
26 # error "Libint2 C++ API requires C++11 support"
27 #endif
28 
29 #include <atomic>
30 #include <cassert>
31 #include <iostream>
32 
33 #include <libint2.h>
34 #include <libint2/util/deprecated.h>
35 #include <libint2/util/singleton.h>
36 #include <libint2/deriv_map.h>
37 
38 namespace libint2 {
39 
40   namespace detail {
41     struct __initializer {
__initializer__initializer42         __initializer() {
43           libint2_static_init();
44           libint2::DerivMapGenerator::initialize();
45         }
~__initializer__initializer46         ~__initializer() {
47           libint2_static_cleanup();
48         }
49     };
50 
verbose_accessor()51     inline std::atomic<bool>& verbose_accessor() {
52       static std::atomic<bool> value{false};
53       return value;
54     }
verbose_stream_accessor()55     inline std::ostream*& verbose_stream_accessor() {
56       static std::ostream* value = &std::clog;
57       return value;
58     }
59   } // namespace libint2::detail
60 
61   /// checks if the libint has been initialized.
62   /// @return true, if libint2::initialize() has been called since the last (if any) call to libint2::finalize()
initialized()63   inline bool initialized() {
64     using namespace detail;
65     return managed_singleton<__initializer>::instance_exists();
66   }
67   /// initializes the libint library if not currently initialized, no-op otherwise
68   /// @param[in] verbose boolean flag that controls the verbosity of messages produced by libint in std::clog . If false, no messages
69   ///            will be produced. The default is false.
70   inline void initialize(bool verbose = false) {
71     if (!initialized()) {
72       using namespace detail;
73       __initializer *x = managed_singleton<__initializer>::instance();
74       (void) x;  // to suppress unused variable warning (not guaranteed to work) TODO revise when upgrade to C++17
75       assert(x != nullptr);
76       verbose_accessor() = verbose;
77     }
78   }
79 
80   /// initializes the libint library if not currently initialized, no-op otherwise
81   /// @param[in] os the output stream to which verbose diagnostics will be written (if @c initialize(true) is used, will write to @c std::clog )
initialize(std::ostream & os)82   inline void initialize(std::ostream& os) {
83     if (!initialized()) {
84       initialize(true);
85       using namespace detail;
86       verbose_stream_accessor() = &os;
87     }
88   }
89   /// finalizes the libint library.
finalize()90   inline void finalize() {
91     if (initialized()) {
92       using namespace detail;
93       managed_singleton<__initializer>::delete_instance();
94       verbose_accessor() = true;
95       verbose_stream_accessor() = &std::clog;
96     }
97   }
98   /// Accessor for the disgnostics stream
99   /// @return the stream to which the diagnostics will be written if verbose() returns true
verbose_stream()100   inline std::ostream& verbose_stream() {
101     return *detail::verbose_stream_accessor();
102   }
103   /// Accessor for the verbose flag
104   /// @return true if the library is permitted to generate diagnostic messages to the stream returned by verbose_stream(); always returns false
105   ///         if @c initialized()==false
verbose()106   inline bool verbose() {
107     if (initialized()) {
108       return detail::verbose_accessor();
109     } else {
110       return false;
111     }
112   }
113 }
114 
115 #endif /* _libint2_src_lib_libint_initialize_h_ */
116 
117