1 /*
2   This file is part of MADNESS.
3 
4   Copyright (C) 2007,2010 Oak Ridge National Laboratory
5 
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2 of the License, or
9   (at your option) any later version.
10 
11   This program 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 General Public License for more details.
15 
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 
20   For more information please contact:
21 
22   Robert J. Harrison
23   Oak Ridge National Laboratory
24   One Bethel Valley Road
25   P.O. Box 2008, MS-6367
26 
27   email: harrisonrj@ornl.gov
28   tel:   865-241-3937
29   fax:   865-572-0680
30 */
31 
32 #ifndef MADNESS_WORLD_PRINT_H__INCLUDED
33 #define MADNESS_WORLD_PRINT_H__INCLUDED
34 
35 /**
36  \file print.h
37  \brief Defines simple templates for printing to \c std::cout "a la Python".
38  \ingroup libraries
39 */
40 
41 #include <type_traits>
42 #include <iostream>
43 #include <complex>
44 #include <list>
45 #include <vector>
46 #include <madness/world/worldmutex.h>
47 
48 #ifdef BRAINDEAD
49 // Cray XT nonsense
50 #define ENDL "\n"
51 
52 #else
53 
54 #define ENDL std::endl
55 
56 #endif
57 
58 
59 namespace madness {
60 
61     /// \addtogroup libraries
62     /// @{
63 
64     /// Easy printing of complex numbers.
65 
66     /// \tparam T The "real" type of the complex number.
67     /// \param[in,out] s The output stream.
68     /// \param[in] c The complex number.
69     /// \return The output stream (for chaining).
70     template <typename T>
71     std::ostream& operator<<(std::ostream& s, const std::complex<T>& c) {
72         s << c.real() << "+" << c.imag() << "j";
73         return s;
74     }
75 
76     /// Easy printing of pairs.
77 
78     /// \tparam T Type 1 of the pair.
79     /// \tparam U Type 2 of the pair.
80     /// \param[in,out] s The output stream.
81     /// \param[in] p The pair.
82     /// \return The output stream (for chaining).
83     template <typename T, typename U>
84     std::ostream& operator<<(std::ostream& s, const std::pair<T,U>& p) {
85         s << "(" << p.first << "," << p.second << ")";
86         return s;
87     }
88 
89     /// Easy printing of lists.
90 
91     /// \tparam T Type stored in the list.
92     /// \param[in,out] s The output stream.
93     /// \param[in] c The list.
94     /// \return The output stream (for chaining).
95     template <typename T>
96     std::ostream& operator<<(std::ostream& s, const std::list<T>& c) {
97         s << "[";
98         typename std::list<T>::const_iterator it = c.begin();
99         while (it != c.end()) {
100             s << *it;
101             ++it;
102             if (it != c.end()) s << ", ";
103         };
104         s << "]";
105         return s;
106     }
107 
108     /// Easy printing of vectors.
109 
110     /// \tparam T Type stored in the vector.
111     /// \param[in,out] s The output stream.
112     /// \param[in] c The vector.
113     /// \return The output stream (for chaining).
114     template <typename T>
115     std::ostream& operator<<(std::ostream& s, const std::vector<T>& c) {
116         s << "[";
117         typename std::vector<T>::const_iterator it = c.begin();
118         while (it != c.end()) {
119             s << *it;
120             ++it;
121             if (it != c.end()) s << ", ";
122         };
123         s << "]";
124         return s;
125     }
126 
127     /// Easy printing of fixed dimension arrays.
128 
129     /// STL I/O already does char (thus the \c enable_if business).
130     /// \tparam T Type of data in the array.
131     /// \tparam N Size of the array.
132     /// \param[in,out] s The output stream.
133     /// \param[in] v The array.
134     /// \return The output stream (for chaining).
135     template <typename T, std::size_t N>
136     typename std::enable_if<!std::is_same<T,char>::value, std::ostream&>::type
137     operator<<(std::ostream& s, const T(&v)[N]) {
138         s << "[";
139         for (std::size_t i=0; i<N; ++i) {
140             s << v[i];
141             if (i != (N-1)) s << ",";
142         }
143         s << "]";
144         return s;
145     }
146 
147     /// Print a string justified on the left to start at the given column with optional underlining.
148     void print_justified(const char* s, int column=0, bool underline=true);
149 
150     /// Print a string centered at the given column with optional underlining.
151     void print_centered(const char* s, int column=40, bool underline=true);
152 
153 
154     // the "print" function and functions to help handle the variadic templates
155 
156     /// Helper function for \c print. Base case.
157 
158     /// This gets called recursively when there are no items left to print.
159     /// \param[in,out] out Output stream.
160     /// \return The output stream (for chaining).
print_helper(std::ostream & out)161     inline std::ostream& print_helper(std::ostream& out) {
162         return out;
163     }
164 
165     /// \brief Helper function for \c print. Prints the first item (\c t) and
166     ///    recursively passes on the other items.
167 
168     /// \tparam T Type of the item to print in this call.
169     /// \tparam Ts Argument pack type for the remaining items.
170     /// \param[in,out] out Output stream.
171     /// \param[in] t The item to print in this call.
172     /// \param[in] ts The remaining items in the argument pack (they get
173     ///    recursively passed on).
174     /// \return The output stream (for chaining).
175     template <typename T, typename... Ts>
print_helper(std::ostream & out,const T & t,const Ts &...ts)176     inline std::ostream& print_helper(std::ostream& out,
177                                       const T& t, const Ts&... ts) {
178         out << ' ' << t;
179         return print_helper(out, ts...);
180     }
181 
182     /// \brief Print items to \c std::cout (items separated by spaces) and
183     ///    terminate with a new line
184 
185     /// The first item is printed here so that it isn't preceded by a space.
186     /// \tparam T Type of the first item to be printed.
187     /// \tparam Ts Argument pack type for the items to be printed.
188     /// \param[in] t The first item to be printed.
189     /// \param[in] ts The remaining items to be printed in the argument pack.
190     template<typename T, typename... Ts>
print(const T & t,const Ts &...ts)191     void print(const T& t, const Ts&... ts) {
192         ScopedMutex<Mutex> safe(detail::printmutex);
193         std::cout << t;
194         print_helper(std::cout, ts...) << ENDL;
195     }
196 
197     /// \brief Print items to \c std::cerr (items separated by spaces) and
198     ///    terminate with a new line
199 
200     /// The first item is printed here so that it isn't preceded by a space.
201     /// \tparam T Type of the first item to be printed.
202     /// \tparam Ts Argument pack type for the items to be printed.
203     /// \param[in] t The first item to be printed.
204     /// \param[in] ts The remaining items to be printed in the argument pack.
205     template<typename T, typename... Ts>
print_error(const T & t,const Ts &...ts)206     void print_error(const T& t, const Ts&... ts) {
207         ScopedMutex<Mutex> safe(detail::printmutex);
208         std::cerr << t;
209         print_helper(std::cerr, ts...) << ENDL;
210     }
211 
212     /// @}
213 
214 }
215 #endif // MADNESS_WORLD_PRINT_H__INCLUDED
216