Cantera  2.0
PrintCtrl.cpp
Go to the documentation of this file.
1 /**
2  * @file PrintCtrl.cpp
3  * Definitions for a simple class that augments the streams printing capabilities
4  * (see \ref Cantera::PrintCtrl).
5  */
6 /*
7  * Copyright 2004 Sandia Corporation. Under the terms of Contract
8  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
9  * retains certain rights in this software.
10  * See file License.txt for licensing information.
11  */
12 
13 #include <cmath>
14 
15 #include <iostream>
16 #include <fstream>
17 
18 #include "cantera/base/PrintCtrl.h"
19 
20 using namespace std;
21 
22 namespace Cantera
23 {
24 
25 
26 // Storage for the global crop flag
27 PrintCtrl::CROP_TYPE_GLOBAL PrintCtrl::GlobalCrop = GCT_NOPREF;
28 
29 
30 PrintCtrl::PrintCtrl(std::ostream& coutProxy, int Ndec,
31  CROP_TYPE ctlocal) :
32  m_cout(coutProxy),
33  m_Ndec(Ndec),
34  m_precision(12),
35  m_wMin(9),
36  m_wMax(19),
37  m_cropCntrl(ctlocal)
38 {
39 
40 }
41 
42 // Print a double using scientific notation
43 /*
44  * Prints a double using scientific notation in a
45  * fixed number of spaces
46  *
47  *
48  * @param d double to be printed
49  * @param w Number of spaces to use
50  * @param p Precision
51  *
52  *
53  */
54 void PrintCtrl::pr_de_c10(const double din, int p, const int wMin,
55  const int wMax)
56 {
57  double d = cropAbs10(din, m_Ndec);
58  pr_de(d, p, wMin, wMax);
59 }
60 
61 // Print a double using scientific notation
62 /*
63  * Prints a double using scientific notation in a
64  * fixed number of spaces. Rounding of the last digit is carried out
65  * by the standard c++ printing utilities.
66  *
67  * @param d double to be printed
68  * @param w Number of spaces to use
69  * @param p Precision
70  */
71 void PrintCtrl::pr_de(const double d, int sigDigIn, const int wMinIn,
72  const int wMaxIn)
73 {
74  int p = m_precision;
75  if (sigDigIn != -1) {
76  p = sigDigIn-1;
77  if (p < 0) {
78  p = 0;
79  }
80  }
81 
82  int wMin = m_wMin;
83  if (wMinIn != -1) {
84  wMin = wMinIn;
85  if (wMin < 1) {
86  wMin = 1;
87  }
88  }
89 
90  int wMax = m_wMax;
91  if (wMaxIn != -1) {
92  wMax = wMaxIn;
93  if (wMax < 1) {
94  wMax = 1;
95  }
96  }
97 
98  if (wMin > wMax) {
99  wMax = wMin;
100  }
101 
102  // Have to do the wMax ourselves, since C++ doesn't seem to
103  // have a streams manipulator to do this !?!
104  double dfabs = fabs(d);
105  // This is the normal length assuming no sign and an 1.0E+04
106  // formated exponented
107  int requestedLength = 6 + p;
108  if (d < 0.0) {
109  requestedLength++;
110  }
111  if (dfabs < 9.9999999999E-99) {
112  requestedLength++;
113  }
114  if (dfabs > 9.9999999999E99) {
115  requestedLength++;
116  }
117  if (requestedLength > wMax) {
118  p -= (requestedLength - wMax);
119  if (p < 0) {
120  p = 0;
121  }
122  }
123 
124  // Set to upper case and scientific notation
125  m_cout.setf(ios_base::scientific | ios_base::uppercase);
126  int wold = (int) m_cout.width(wMin);
127  int pold = (int) m_cout.precision(p);
128 
129  m_cout << d;
130  // Return the precision to the previous value;
131  m_cout.precision(pold);
132  m_cout.unsetf(ios_base::scientific);
133 
134  // Return width to original
135  m_cout.width(wold);
136 }
137 
138 // Croup a double at a certain decade level
139 /*
140  * This routine will crop a floating point number at a certain
141  * decade lvl. In other words everything below a power of 10^Ndec
142  * will be deleted.
143  * Note, it currently does not do rounding of the last digit.
144  *
145  * @param d Double to be cropped
146  * @param nSig Number of significant digits
147  * example:
148  * d = 1.1305E-15;
149  * Ndec = -16;
150  * This routine will return 1.1E-15
151  *
152  * d = 8.0E-17
153  * Ndec = -16
154  * This routine will return 0.0
155  */
156 double PrintCtrl::cropAbs10(const double d, int Ndec) const
157 {
158  if (!doCrop()) {
159  return d;
160  }
161  if (Ndec < -301 || Ndec > 301) {
162  return d;
163  }
164  double dfabs = fabs(d);
165  double pdec = pow(10.0, (double) Ndec);
166  if (dfabs < pdec) {
167  return 0.0;
168  }
169  double dl10 = log10(dfabs);
170  int N10 = (int) dl10;
171  if (dl10 > -0.0) {
172  N10 += 1;
173  }
174  int nsig = N10 - Ndec;
175  double retn = cropSigDigits(d, nsig);
176  return retn;
177 }
178 
179 // Crop a double at a certain number of significant digits
180 /*
181  * This routine will crop a floating point number at a certain
182  * number of significant digits. Note, it currently does
183  * rounding up of the last digit.
184  *
185  * example:
186  * d = 1.0305E-15;
187  * nsig = 3;
188  * This routine will return 1.03E-15
189  */
190 double PrintCtrl::cropSigDigits(const double d, int nSig) const
191 {
192  if (!doCrop()) {
193  return d;
194  }
195  if (nSig <=0) {
196  nSig = 1;
197  }
198  if (nSig >=9) {
199  nSig = 9;
200  }
201  double sgn = 1.0;
202  if (d < 0.0) {
203  sgn = -1.0;
204  }
205  double dfabs = fabs(d);
206  double dl10 = log10(dfabs);
207  int N10 = (int) dl10;
208  if (dl10 > -0.0) {
209  N10 += 1;
210  }
211  int E10 = -N10 + nSig ;
212  double pfabs = dfabs * pow(10.0, (double) E10);
213  pfabs *= (1.0 + 1.0E-14);
214  long int nfabs = (long int) pfabs;
215  double remainder = pfabs - nfabs;
216  if (remainder > 0.5) {
217  nfabs++;
218  }
219  double paltabs = (double) nfabs;
220  double daltabs = paltabs * pow(10.0, (double) -E10);
221  return (sgn * daltabs);
222 }
223 
224 // Set the default value of N decade
225 /*
226  * @param Ndec new value of Ndec
227  *
228  * @return returns the old value of Ndec
229  */
230 int PrintCtrl::setNdec(int Ndec)
231 {
232  int nold = m_Ndec;
233  m_Ndec = Ndec;
234  return nold;
235 }
236 
237 // Set the default significant digits to output
238 /*
239  * @param nSigDigits new value of the sig digits
240  *
241  * @return returns the old value of Ndec
242  */
243 int PrintCtrl::setSigDigits(int nSigDigits)
244 {
245  int nold = m_precision + 1;
246  m_precision = nSigDigits - 1;
247  if (m_precision < 0) {
248  m_precision = 0;
249  }
250  return nold;
251 }
252 
253 // Set the default minimum width
254 /*
255  * @param wmin Default minimum width
256  *
257  * @return returns the old default
258  */
259 int PrintCtrl::setWmin(int wmin)
260 {
261  int nold = m_wMin;
262  m_wMin = wmin;
263  return nold;
264 }
265 
266 
267 // Set the default maximum width
268 /*
269  * @param wmin Default maximum width
270  *
271  * @return returns the old default
272  */
273 int PrintCtrl::setWmax(int wmax)
274 {
275  int nold = m_wMax;
276  m_wMax = wmax;
277  return nold;
278 }
279 
280 bool PrintCtrl::doCrop() const
281 {
282  bool retn = ((m_cropCntrl == CT_ON) || (m_cropCntrl == CT_ON_GLOBALOBEY));
283  if (m_cropCntrl == CT_ON_GLOBALOBEY) {
284  if (GlobalCrop == GCT_NOCROP) {
285  retn = false;
286  }
287  } else if (m_cropCntrl == CT_OFF_GLOBALOBEY) {
288  if (GlobalCrop == GCT_CROP) {
289  retn = true;
290  }
291  }
292  return retn;
293 }
294 
296 {
297  m_cropCntrl = ctlocal;
298 }
299 }