cloudy  trunk
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
service.cpp
Go to the documentation of this file.
1 /* This file is part of Cloudy and is copyright (C)1978-2017 by Gary J. Ferland and
2  * others. For conditions of distribution and use see copyright notice in license.txt */
3 /*
4 * a set of routines that are widely used across the code for various
5 * housekeeping chores. These do not do any physics and are unlikely to
6 * change over time. The prototypes are in cddefines.h and so are
7 * automatically picked up by all routines
8 */
9 /*FFmtRead scan input line for free format number */
10 /*caps convert input command line (through eol) to ALL CAPS */
11 /*ShowMe produce request to send information to GJF after a crash */
12 /*AnuUnit produce continuum energy in arbitrary units */
13 /*cap4 convert first 4 char of input line chLab into chCAP all in caps, null termination */
14 /*insane set flag saying that insanity has occurred */
15 /*nMatch determine whether match to a keyword occurs on command line,
16  * return value is 0 if no match, and position of match within string if hit */
17 /*fudge enter fudge factors, or some arbitrary number, with fudge command*/
18 /*GetQuote get any name between double quotes off command line
19  * return string as chLabel, is null terminated */
20 /*qip compute pow(x,n) for positive integer n through repeated squares */
21 /*dsexp safe exponential function for doubles */
22 /*sexp safe exponential function */
23 /*TestCode set flag saying that test code is in place */
24 /*CodeReview - placed next to code that needs to be checked */
25 /*fixit - say that code needs to be fixed */
26 /*broken set flag saying that the code is broken, */
27 /*dbg_printf is a debug print routine that was provided by Peter Teuben,
28  * as a component from his NEMO package. It offers run-time specification
29  * of the level of debugging */
30 /*qg32 32 point Gaussian quadrature, original Fortran given to Gary F by Jim Lattimer */
31 /*TotalInsanity general error handler for something that cannot happen */
32 /*BadRead general error handler for trying to read data, but failing */
33 /*MyMalloc wrapper for malloc(). Returns a good pointer or dies. */
34 /*spsort netlib routine to sort array returning sorted indices */
35 /*chLineLbl use information in line transfer arrays to generate a line label *
36  * this label is null terminated */
37 /*chIonLbl use information in line array to generate a null terminated ion label in "Fe 2" */
38 /*csphot returns photoionization cross section from opacity stage using std pointers */
39 /*MyAssert a version of assert that fails gracefully */
40 /*RandGauss normal random variate generator */
41 /*MyGaussRand a wrapper for RandGauss, see below */
42 
43 #include "cdstd.h"
44 #include <cstdarg> /* ANSI variable arg macros */
45 #include "cddefines.h"
46 #include "service.h"
47 #include "cddrive.h"
48 #include "called.h"
49 #include "opacity.h"
50 #include "rfield.h"
51 #include "hextra.h"
52 #include "struc.h"
53 #include "fudgec.h"
54 #include "broke.h"
55 #include "trace.h"
56 #include "input.h"
57 #include "save.h"
58 #include "version.h"
59 #include "warnings.h"
60 #include "conv.h"
61 #include "atmdat.h"
62 #include "mole.h"
63 #include "prt.h"
64 #include "integrate.h"
65 
66 #ifdef __CYGWIN__
67 extern "C" { int vsnprintf(char*, size_t, const char*, va_list); }
68 #endif
69 
70 /*read_whole_line - safe version of fgets - read a line,
71  * return null if cannot read line or if input line is too long */
72 char *read_whole_line( char *chLine , int nChar , FILE *ioIN )
73 {
74  char *chRet;
75 
76  DEBUG_ENTRY( "read_whole_line()" );
77 
78  /* wipe the buffer to prevent the code from accidentally picking up on previous input */
79  memset( chLine, 0, (size_t)nChar );
80 
81  /* this always writes a '\0' character, even if line does not fit in buffer
82  * the terminating newline is copied only if the line does fit in the buffer */
83  if( (chRet = fgets( chLine, nChar, ioIN )) == NULL )
84  return NULL;
85 
86  long lineLength = strlen( chRet );
87  //fprintf(ioQQQ , "DEBUG reading:%s\n" , chLine);
88  //fprintf(ioQQQ , "DEBUG length is %li nChar is %i \n", lineLength , nChar);
89 
90  /* return null if input string is longer than nChar-1 (including terminating newline),
91  * the longest we can read. Print and return null but chLine still has as much of
92  * the line as could be placed in the buffer */
93  if( lineLength>=nChar-1 )
94  {
95  if( called.lgTalk )
96  fprintf( ioQQQ, "DISASTER PROBLEM read_whole_line found input"
97  " with a line too long to be read, limit is %i char. "
98  "Start of line follows:\n%s\n",
99  nChar , chLine );
100 
101  lgAbort = true;
102  return NULL;
103  }
104  return chRet;
105 }
106 
108 void Split(const string& str, // input string
109  const string& sep, // separator, may be multiple characters
110  vector<string>& lst, // the separated items will be appended here
111  split_mode mode) // SPM_RELAX, SPM_KEEP_EMPTY, or SPM_STRICT; see cddefines.h
112 {
113  DEBUG_ENTRY( "Split()" );
114 
115  bool lgStrict = ( mode == SPM_STRICT );
116  bool lgKeep = ( mode == SPM_KEEP_EMPTY );
117  bool lgFail = false;
118  string::size_type ptr1 = 0;
119  string::size_type ptr2 = str.find( sep );
120  string sstr = str.substr( ptr1, ptr2-ptr1 );
121  if( sstr.length() > 0 )
122  lst.push_back( sstr );
123  else {
124  if( lgStrict ) lgFail = true;
125  if( lgKeep ) lst.push_back( sstr );
126  }
127  while( ptr2 != string::npos ) {
128  // the separator is skipped
129  ptr1 = ptr2 + sep.length();
130  if( ptr1 < str.length() ) {
131  ptr2 = str.find( sep, ptr1 );
132  sstr = str.substr( ptr1, ptr2-ptr1 );
133  if( sstr.length() > 0 )
134  lst.push_back( sstr );
135  else {
136  if( lgStrict ) lgFail = true;
137  if( lgKeep ) lst.push_back( sstr );
138  }
139  }
140  else {
141  ptr2 = string::npos;
142  if( lgStrict ) lgFail = true;
143  if( lgKeep ) lst.push_back( "" );
144  }
145  }
146  if( lgFail )
147  {
148  fprintf( ioQQQ, " A syntax error occurred while splitting the string: \"%s\"\n", str.c_str() );
149  fprintf( ioQQQ, " The separator is \"%s\". Empty substrings are not allowed.\n", sep.c_str() );
151  }
152 }
153 
154 // remove whitespace from the end of a string
155 void trimTrailingWhiteSpace( string &str )
156 {
157  size_t pos = str.find_last_not_of(" \t");
158  // If this fails, everything is whitespace.
159  if ( pos != string::npos )
160  str.erase( pos+1 );
161  return;
162 }
163 
164 // remove whitespace from the end of a string
165 void trimTrailingWhiteSpace( char *str )
166 {
167  int pos = strlen( str );
168  while( pos > 0 && (str[pos-1]==' ' || str[pos-1]=='\t' ))
169  --pos;
170  str[pos] = '\0';
171  // If this fails, everything is whitespace.
172  // ASSERT( pos != 0 );
173  return;
174 }
175 
176 /* a version of assert that fails gracefully */
177 void MyAssert(const char *file, int line, const char *comment)
178 {
179  DEBUG_ENTRY( "MyAssert()" );
180 
181  fprintf(ioQQQ,"\n\n\n PROBLEM DISASTER\n An assert has been thrown, this is bad.\n");
182  fprintf(ioQQQ," %s\n",comment);
183  fprintf(ioQQQ," It happened in the file %s at line number %i\n", file, line );
184  fprintf(ioQQQ," This is iteration %li, nzone %li, fzone %.2f, lgSearch=%c.\n",
185  iteration ,
186  nzone ,
187  fnzone ,
188  TorF(conv.lgSearch) );
189 
190  ShowMe();
191 # ifdef OLD_ASSERT
193 # endif
194 }
195 
196 /*AnuUnit produce continuum energy in arbitrary units, as determined by ChkUnits() */
197 double AnuUnit(realnum energy_ryd)
198 {
199  DEBUG_ENTRY( "AnuUnit()" );
200 
201  return Energy((double)energy_ryd).get(save.chConSavEnr[save.ipConPun]);
202 }
203 
204 /*ShowMe produce request to send information to GJF after a crash */
205 void ShowMe(void)
206 {
207 
208  DEBUG_ENTRY( "ShowMe()" );
209 
210  /* print info if output unit is defined */
211  if( ioQQQ != NULL )
212  {
213  /* >>chng 06 mar 02 - check if molecular but cosmic rays are ignored */
214  molezone* h2 = findspecieslocal("H2");
215  // molecular species may not be set up yet, so check for NULL pointer...
216  if( (hextra.cryden == 0.) && h2 != NULL && h2->xFracLim > 0.1 )
217  {
218  fprintf( ioQQQ, " >>> \n >>> \n >>> Cosmic rays are not included and the gas is molecular. "
219  "THIS IS KNOWN TO BE UNSTABLE. Add cosmic rays and try again.\n >>> \n >>>\n\n");
220  }
221  else
222  {
223  fprintf( ioQQQ, "\n\n\n" );
224  fprintf( ioQQQ, " vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv \n" );
225  fprintf( ioQQQ, " > PROBLEM DISASTER PROBLEM DISASTER. <\n" );
226  fprintf( ioQQQ, " > Sorry, something bad has happened. <\n" );
227  fprintf( ioQQQ, " > Please post this on the Cloudy web site <\n" );
228  fprintf( ioQQQ, " > discussion board at www.nublado.org <\n" );
229  fprintf( ioQQQ, " > Please send all following information: <\n" );
230  fprintf( ioQQQ, " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \n" );
231  fprintf( ioQQQ, "\n\n" );
232 
233 
234  fprintf( ioQQQ, " Cloudy version number is %s\n",
235  t_version::Inst().chVersion );
236  fprintf( ioQQQ, " %s\n\n", t_version::Inst().chInfo );
237 
238  fprintf( ioQQQ, "%5ld warnings,%3ld cautions,%3ld temperature failures. Messages follow.\n",
240 
241  /* print the warnings first */
242  cdWarnings(ioQQQ);
243 
244  /* now print the cautions */
245  cdCautions(ioQQQ);
246 
247  /* now output the commands */
249 
250  /* if init command was present, this is the number of lines in it -
251  * if no init then still set to zero as done in cdInit */
252  if( input.nSaveIni )
253  {
254  fprintf(ioQQQ," This input stream included an init file.\n");
255  fprintf(ioQQQ," If this init file is not part of the standard Cloudy distribution\n");
256  fprintf(ioQQQ," then I will need a copy of it too.\n");
257  }
258  }
259  }
260  return;
261 }
262 
263 /*cap4 convert first 4 char of input line chLab into chCAP all in caps, null termination */
264 void cap4(
265  char *chCAP , /* output string, cap'd first 4 char of chLab, */
266  /* with null terminating */
267  const char *chLab) /* input string ending with eol*/
268 {
269  long int /*chr,*/
270  i;
271 
272  DEBUG_ENTRY( "cap4()" );
273 
274  /* convert 4 character string in chLab to ALL CAPS in chCAP */
275  for( i=0; i < 4; i++ )
276  {
277  /* toupper is function in ctype that converts to upper case */
278  chCAP[i] = toupper( chLab[i] );
279  }
280 
281  /* now end string with eol */
282  chCAP[4] = '\0';
283  return;
284 }
285 
286 /*uncaps convert input command line (through eol) to all lowercase */
287 void uncaps(char *chCard )
288 {
289  long int i;
290 
291  DEBUG_ENTRY( "caps()" );
292 
293  /* convert full character string in chCard to ALL CAPS */
294  i = 0;
295  while( chCard[i]!= '\0' )
296  {
297  chCard[i] = tolower( chCard[i] );
298  ++i;
299  }
300  return;
301 }
302 
303 /*caps convert input command line (through eol) to ALL CAPS */
304 void caps(char *chCard )
305 {
306  long int i;
307 
308  DEBUG_ENTRY( "caps()" );
309 
310  /* convert full character string in chCard to ALL CAPS */
311  i = 0;
312  while( chCard[i]!= '\0' )
313  {
314  chCard[i] = toupper( chCard[i] );
315  ++i;
316  }
317  return;
318 }
319 
320 static const double pos_pow10[] = {
321  1.e+000, 1.e+001, 1.e+002, 1.e+003, 1.e+004, 1.e+005, 1.e+006, 1.e+007, 1.e+008, 1.e+009,
322  1.e+010, 1.e+011, 1.e+012, 1.e+013, 1.e+014, 1.e+015, 1.e+016, 1.e+017, 1.e+018, 1.e+019,
323  1.e+020, 1.e+021, 1.e+022, 1.e+023, 1.e+024, 1.e+025, 1.e+026, 1.e+027, 1.e+028, 1.e+029,
324  1.e+030, 1.e+031, 1.e+032, 1.e+033, 1.e+034, 1.e+035, 1.e+036, 1.e+037, 1.e+038, 1.e+039,
325  1.e+040, 1.e+041, 1.e+042, 1.e+043, 1.e+044, 1.e+045, 1.e+046, 1.e+047, 1.e+048, 1.e+049,
326  1.e+050, 1.e+051, 1.e+052, 1.e+053, 1.e+054, 1.e+055, 1.e+056, 1.e+057, 1.e+058, 1.e+059,
327  1.e+060, 1.e+061, 1.e+062, 1.e+063, 1.e+064, 1.e+065, 1.e+066, 1.e+067, 1.e+068, 1.e+069,
328  1.e+070, 1.e+071, 1.e+072, 1.e+073, 1.e+074, 1.e+075, 1.e+076, 1.e+077, 1.e+078, 1.e+079,
329  1.e+080, 1.e+081, 1.e+082, 1.e+083, 1.e+084, 1.e+085, 1.e+086, 1.e+087, 1.e+088, 1.e+089,
330  1.e+090, 1.e+091, 1.e+092, 1.e+093, 1.e+094, 1.e+095, 1.e+096, 1.e+097, 1.e+098, 1.e+099,
331  1.e+100, 1.e+101, 1.e+102, 1.e+103, 1.e+104, 1.e+105, 1.e+106, 1.e+107, 1.e+108, 1.e+109,
332  1.e+110, 1.e+111, 1.e+112, 1.e+113, 1.e+114, 1.e+115, 1.e+116, 1.e+117, 1.e+118, 1.e+119,
333  1.e+120, 1.e+121, 1.e+122, 1.e+123, 1.e+124, 1.e+125, 1.e+126, 1.e+127, 1.e+128, 1.e+129,
334  1.e+130, 1.e+131, 1.e+132, 1.e+133, 1.e+134, 1.e+135, 1.e+136, 1.e+137, 1.e+138, 1.e+139,
335  1.e+140, 1.e+141, 1.e+142, 1.e+143, 1.e+144, 1.e+145, 1.e+146, 1.e+147, 1.e+148, 1.e+149,
336  1.e+150, 1.e+151, 1.e+152, 1.e+153, 1.e+154, 1.e+155, 1.e+156, 1.e+157, 1.e+158, 1.e+159,
337  1.e+160, 1.e+161, 1.e+162, 1.e+163, 1.e+164, 1.e+165, 1.e+166, 1.e+167, 1.e+168, 1.e+169,
338  1.e+170, 1.e+171, 1.e+172, 1.e+173, 1.e+174, 1.e+175, 1.e+176, 1.e+177, 1.e+178, 1.e+179,
339  1.e+180, 1.e+181, 1.e+182, 1.e+183, 1.e+184, 1.e+185, 1.e+186, 1.e+187, 1.e+188, 1.e+189,
340  1.e+190, 1.e+191, 1.e+192, 1.e+193, 1.e+194, 1.e+195, 1.e+196, 1.e+197, 1.e+198, 1.e+199,
341  1.e+200, 1.e+201, 1.e+202, 1.e+203, 1.e+204, 1.e+205, 1.e+206, 1.e+207, 1.e+208, 1.e+209,
342  1.e+210, 1.e+211, 1.e+212, 1.e+213, 1.e+214, 1.e+215, 1.e+216, 1.e+217, 1.e+218, 1.e+219,
343  1.e+220, 1.e+221, 1.e+222, 1.e+223, 1.e+224, 1.e+225, 1.e+226, 1.e+227, 1.e+228, 1.e+229,
344  1.e+230, 1.e+231, 1.e+232, 1.e+233, 1.e+234, 1.e+235, 1.e+236, 1.e+237, 1.e+238, 1.e+239,
345  1.e+240, 1.e+241, 1.e+242, 1.e+243, 1.e+244, 1.e+245, 1.e+246, 1.e+247, 1.e+248, 1.e+249,
346  1.e+250, 1.e+251, 1.e+252, 1.e+253, 1.e+254, 1.e+255, 1.e+256, 1.e+257, 1.e+258, 1.e+259,
347  1.e+260, 1.e+261, 1.e+262, 1.e+263, 1.e+264, 1.e+265, 1.e+266, 1.e+267, 1.e+268, 1.e+269,
348  1.e+270, 1.e+271, 1.e+272, 1.e+273, 1.e+274, 1.e+275, 1.e+276, 1.e+277, 1.e+278, 1.e+279,
349  1.e+280, 1.e+281, 1.e+282, 1.e+283, 1.e+284, 1.e+285, 1.e+286, 1.e+287, 1.e+288, 1.e+289,
350  1.e+290, 1.e+291, 1.e+292, 1.e+293, 1.e+294, 1.e+295, 1.e+296, 1.e+297, 1.e+298, 1.e+299,
351  1.e+300, 1.e+301, 1.e+302, 1.e+303, 1.e+304, 1.e+305, 1.e+306, 1.e+307, 1.e+308
352 };
353 
354 static const int max_pow10 = int(sizeof(pos_pow10)/sizeof(pos_pow10[0]) - 1);
355 
356 static const double neg_pow10[] = {
357  1.e-000, 1.e-001, 1.e-002, 1.e-003, 1.e-004, 1.e-005, 1.e-006, 1.e-007, 1.e-008, 1.e-009,
358  1.e-010, 1.e-011, 1.e-012, 1.e-013, 1.e-014, 1.e-015, 1.e-016, 1.e-017, 1.e-018, 1.e-019,
359  1.e-020, 1.e-021, 1.e-022, 1.e-023, 1.e-024, 1.e-025, 1.e-026, 1.e-027, 1.e-028, 1.e-029,
360  1.e-030, 1.e-031, 1.e-032, 1.e-033, 1.e-034, 1.e-035, 1.e-036, 1.e-037, 1.e-038, 1.e-039,
361  1.e-040, 1.e-041, 1.e-042, 1.e-043, 1.e-044, 1.e-045, 1.e-046, 1.e-047, 1.e-048, 1.e-049,
362  1.e-050, 1.e-051, 1.e-052, 1.e-053, 1.e-054, 1.e-055, 1.e-056, 1.e-057, 1.e-058, 1.e-059,
363  1.e-060, 1.e-061, 1.e-062, 1.e-063, 1.e-064, 1.e-065, 1.e-066, 1.e-067, 1.e-068, 1.e-069,
364  1.e-070, 1.e-071, 1.e-072, 1.e-073, 1.e-074, 1.e-075, 1.e-076, 1.e-077, 1.e-078, 1.e-079,
365  1.e-080, 1.e-081, 1.e-082, 1.e-083, 1.e-084, 1.e-085, 1.e-086, 1.e-087, 1.e-088, 1.e-089,
366  1.e-090, 1.e-091, 1.e-092, 1.e-093, 1.e-094, 1.e-095, 1.e-096, 1.e-097, 1.e-098, 1.e-099,
367  1.e-100, 1.e-101, 1.e-102, 1.e-103, 1.e-104, 1.e-105, 1.e-106, 1.e-107, 1.e-108, 1.e-109,
368  1.e-110, 1.e-111, 1.e-112, 1.e-113, 1.e-114, 1.e-115, 1.e-116, 1.e-117, 1.e-118, 1.e-119,
369  1.e-120, 1.e-121, 1.e-122, 1.e-123, 1.e-124, 1.e-125, 1.e-126, 1.e-127, 1.e-128, 1.e-129,
370  1.e-130, 1.e-131, 1.e-132, 1.e-133, 1.e-134, 1.e-135, 1.e-136, 1.e-137, 1.e-138, 1.e-139,
371  1.e-140, 1.e-141, 1.e-142, 1.e-143, 1.e-144, 1.e-145, 1.e-146, 1.e-147, 1.e-148, 1.e-149,
372  1.e-150, 1.e-151, 1.e-152, 1.e-153, 1.e-154, 1.e-155, 1.e-156, 1.e-157, 1.e-158, 1.e-159,
373  1.e-160, 1.e-161, 1.e-162, 1.e-163, 1.e-164, 1.e-165, 1.e-166, 1.e-167, 1.e-168, 1.e-169,
374  1.e-170, 1.e-171, 1.e-172, 1.e-173, 1.e-174, 1.e-175, 1.e-176, 1.e-177, 1.e-178, 1.e-179,
375  1.e-180, 1.e-181, 1.e-182, 1.e-183, 1.e-184, 1.e-185, 1.e-186, 1.e-187, 1.e-188, 1.e-189,
376  1.e-190, 1.e-191, 1.e-192, 1.e-193, 1.e-194, 1.e-195, 1.e-196, 1.e-197, 1.e-198, 1.e-199,
377  1.e-200, 1.e-201, 1.e-202, 1.e-203, 1.e-204, 1.e-205, 1.e-206, 1.e-207, 1.e-208, 1.e-209,
378  1.e-210, 1.e-211, 1.e-212, 1.e-213, 1.e-214, 1.e-215, 1.e-216, 1.e-217, 1.e-218, 1.e-219,
379  1.e-220, 1.e-221, 1.e-222, 1.e-223, 1.e-224, 1.e-225, 1.e-226, 1.e-227, 1.e-228, 1.e-229,
380  1.e-230, 1.e-231, 1.e-232, 1.e-233, 1.e-234, 1.e-235, 1.e-236, 1.e-237, 1.e-238, 1.e-239,
381  1.e-240, 1.e-241, 1.e-242, 1.e-243, 1.e-244, 1.e-245, 1.e-246, 1.e-247, 1.e-248, 1.e-249,
382  1.e-250, 1.e-251, 1.e-252, 1.e-253, 1.e-254, 1.e-255, 1.e-256, 1.e-257, 1.e-258, 1.e-259,
383  1.e-260, 1.e-261, 1.e-262, 1.e-263, 1.e-264, 1.e-265, 1.e-266, 1.e-267, 1.e-268, 1.e-269,
384  1.e-270, 1.e-271, 1.e-272, 1.e-273, 1.e-274, 1.e-275, 1.e-276, 1.e-277, 1.e-278, 1.e-279,
385  1.e-280, 1.e-281, 1.e-282, 1.e-283, 1.e-284, 1.e-285, 1.e-286, 1.e-287, 1.e-288, 1.e-289,
386  1.e-290, 1.e-291, 1.e-292, 1.e-293, 1.e-294, 1.e-295, 1.e-296, 1.e-297, 1.e-298, 1.e-299,
387  1.e-300, 1.e-301, 1.e-302, 1.e-303, 1.e-304, 1.e-305, 1.e-306, 1.e-307
388 };
389 
390 static const int min_pow10 = -int(sizeof(neg_pow10)/sizeof(neg_pow10[0]) - 1);
391 
392 /*FFmtRead scan input line for free format number */
393 double FFmtRead(const char *chCard,
394  long int *ipnt,
395  /* the contents of this array element is the last that will be read */
396  long int last,
397  bool *lgEOL)
398 {
399  DEBUG_ENTRY( "FFmtRead()" );
400 
401  char chr = '\0';
402  const char *eol_ptr = &chCard[last]; // eol_ptr points one beyond last valid char
403  const char *ptr = min(&chCard[*ipnt-1],eol_ptr); // ipnt is on fortran scale
404 
405  if( *ipnt <=0 )
406  {
407  fprintf(ioQQQ, "PROBLEM FFmtRead called with index <=0, ipnt is %li\n",*ipnt);
408  TotalInsanity();
409  }
410  else if( *ipnt >= last )
411  {
412  fprintf(ioQQQ, "PROBLEM FFmtRead called with index >last, ipnt is %li last is %li\n",
413  *ipnt, last);
414  TotalInsanity();
415  }
416 
417  while( ptr < eol_ptr && ( chr = *ptr++ ) != '\0' )
418  {
419  const char *lptr = ptr;
420  char lchr = chr;
421  if( lchr == '-' || lchr == '+' )
422  lchr = *lptr++;
423  if( lchr == '.' )
424  lchr = *lptr;
425  if( isdigit(lchr) )
426  break;
427  }
428 
429  if( ptr >= eol_ptr || chr == '\0' )
430  {
431  *ipnt = last+1;
432  *lgEOL = true;
433  return 0.;
434  }
435 
436  //double atofval = atof(ptr-1);
437 
438  double number = 0.0;
439  int exponent=0, sign=1, expsign=1, scale=0;
440  bool lgCommaFound = false, lgLastComma = false, foundpoint = false, foundexp = false;
441  do
442  {
443  lgCommaFound = lgLastComma;
444  if( chr == ',' )
445  {
446  /* don't complain about comma if it appears after number,
447  as determined by exiting loop before this sets lgCommaFound */
448  lgLastComma = true;
449  }
450  else if (isdigit(chr))
451  {
452  int digit = (chr - '0');
453  if (foundexp)
454  {
455  exponent = 10*exponent+digit;
456  }
457  else
458  {
459  number = 10.0*number+digit;
460  if (foundpoint)
461  ++scale;
462  }
463  }
464  else if (chr == '-')
465  {
466  if (foundexp)
467  {
468  if (exponent != 0 || expsign != 1)
469  break;
470  expsign = -1;
471  }
472  else
473  {
474  if (number != 0 || sign != 1)
475  break;
476  sign = -1;
477  }
478  }
479  else if (tolower(chr) == 'e')
480  {
481  if (foundexp)
482  break;
483  foundexp = true;
484  }
485  else if (chr == '.')
486  {
487  if (foundpoint)
488  break;
489  foundpoint = true;
490  }
491  if( ptr == eol_ptr )
492  break;
493  chr = *ptr++;
494  }
495  while( isdigit(chr) || chr == '.' || chr == '-' || chr == '+' || chr == ',' || chr == 'e' || chr == 'E' );
496 
497  if( lgCommaFound )
498  {
499  fprintf( ioQQQ, " PROBLEM - a comma was found embedded in a number, this is deprecated.\n" );
500  fprintf(ioQQQ, "== %-80s ==\n",chCard);
501  }
502 
503  int expo = expsign*exponent-scale;
504  double value = sign*number;
505  // numbers produced by FFmtRead() should ideally be accurate to 1 ULP, but certainly
506  // better than 3 ULP (the rest of the code relies on this).
507  // To achieve this we use a lookup table of powers of 10, which is also fast...
508  if( expo >= 0 )
509  {
510  while( expo > max_pow10 )
511  {
512  value *= pos_pow10[max_pow10];
513  expo -= max_pow10;
514  }
515  value *= pos_pow10[expo];
516  }
517  else
518  {
519  while( expo < min_pow10 )
520  {
521  value *= neg_pow10[-min_pow10];
522  expo -= min_pow10;
523  }
524  value *= neg_pow10[-expo];
525  }
526 
527  //ASSERT(fp_equal(value,atofval,2));
528  //fprintf(ioQQQ,"%g %g %g\n",value == 0 ? atofval : atofval/value-1.,value,atofval);
529 
530  *ipnt = (long)(ptr - chCard); // ptr already points 1 beyond where next read should start
531  *lgEOL = false;
532  return value;
533 }
534 
535 /*nMatch determine whether match to a keyword occurs on command line,
536  * return value is 0 if no match, and position of match within string if hit */
537 long nMatch(const char *chKey,
538  const char *chCard)
539 {
540  const char *ptr;
541  long Match_v;
542 
543  DEBUG_ENTRY( "nMatch()" );
544 
545  ASSERT( strlen(chKey) > 0 );
546 
547  if( ( ptr = strstr_s( chCard, chKey ) ) == NULL )
548  {
549  /* did not find match, return 0 */
550  Match_v = 0L;
551  }
552  else
553  {
554  /* return position within chCard (fortran scale) */
555  Match_v = (long)(ptr-chCard+1);
556  }
557  return Match_v;
558 }
559 
560 /* fudge enter fudge factors, or some arbitrary number, with fudge command
561  * other sections of the code access these numbers by calling fudge
562  * fudge(0) returns the first number that was entered
563  * prototype for this function is in cddefines.h so that it can be used without
564  * declarations
565  * fudge(-1) queries the routine for the number of fudge parameters that were entered,
566  * zero returned if none */
567 double fudge(long int ipnt)
568 {
569  double fudge_v;
570 
571  DEBUG_ENTRY( "fudge()" );
572 
573  if( ipnt < 0 )
574  {
575  /* this is special case, return number of arguments */
576  fudge_v = fudgec.nfudge;
577  fudgec.lgFudgeUsed = true;
578  }
579  else if( ipnt >= fudgec.nfudge )
580  {
581  fprintf( ioQQQ, " FUDGE factor not entered for array number %3ld\n",
582  ipnt );
584  }
585  else
586  {
587  fudge_v = fudgec.fudgea[ipnt];
588  fudgec.lgFudgeUsed = true;
589  }
590  return fudge_v;
591 }
592 
593 
594 /* GetQuote get any name between double quotes off command line
595  * sets chLabel - null terminated string as chLabel
596  * sets string between quotes to spaces
597  * returns zero for success, 1 for did not find double quotes
598  * lgAbort - true then above, false only set flag*/
600  /* we will generate a label and stuff it here */
601  char *chStringOut,
602  /* line image, we will blank out anything between quotes */
603  char *chCard,
604  char *chCardRaw,
605  /* if true then abort if no double quotes found,
606  * if false then return null string in this case */
607  bool lgAbort )
608 {
609  char *i0, /* pointer to first " */
610  *i1, /* pointer to second ", name is in between */
611  *iLoc; /* pointer to first " in local version of card in calling routine */
612  size_t len;
613 
614  DEBUG_ENTRY( "GetQuote()" );
615 
616  /* find first quote start of string, string begins and ends with quotes */
617  i0 = strchr_s( chCardRaw,'\"' );
618 
619  if( i0 != NULL )
620  {
621  /* get pointer to next quote */
622  i1 = strchr_s( i0+1 ,'\"' );
623  }
624  else
625  {
626  i1 = NULL;
627  }
628 
629  /* check that pointers were not NULL */
630  /* >>chng 00 apr 27, check for i0 and i1 equal not needed anymore, by PvH */
631  if( i0 == NULL || i1 == NULL )
632  {
633  if( lgAbort )
634  {
635  /* lgAbort true, must abort if no string found */
636  fprintf( ioQQQ,
637  " A filename or label must be specified within double quotes, but no quotes were encountered on this command.\n" );
638  fprintf( ioQQQ, " Name must be surrounded by exactly two double quotes, like \"name.txt\". \n" );
639  fprintf( ioQQQ, " The line image follows:\n" );
640  fprintf( ioQQQ, " %s\n", chCardRaw);
641  fprintf( ioQQQ, " Sorry\n" );
643  }
644  else
645  {
646  /* this branch, ok if not present, return null string in that case */
647  chStringOut[0] = '\0';
648  /* return value of 1 indicates did not find double quotes */
649  return 1;
650  }
651  }
652 
653  /* now copy the text in between quotes */
654  len = (size_t)(i1-i0-1);
655  strncpy(chStringOut,i0+1,len);
656  /* strncpy doesn't terminate the label */
657  chStringOut[len] = '\0';
658 
659  /* get pointer to first quote in local copy of line image in calling routine */
660  iLoc = strchr_s( chCard, '\"' );
661  if( iLoc == NULL )
662  TotalInsanity();
663 
664  // blank out label once finished, to not be picked up later
665  // erase quotes as well, so that we can find second label, by PvH
666  while( i0 <= i1 )
667  {
668  *i0 = ' ';
669  *iLoc = ' ';
670  ++i0;
671  ++iLoc;
672  }
673  /* return condition of 0 indicates success */
674  return 0;
675 }
676 
677 /* want to define this only if no native os support exists */
678 #ifndef HAVE_POWI
679 
680 /* powi.c - calc x^n, where n is an integer! */
681 
682 /* Very slightly modified version of power() from Computer Language, Sept. 86,
683  pg 87, by Jon Snader (who extracted the binary algorithm from Donald Knuth,
684  "The Art of Computer Programming", vol 2, 1969).
685  powi() will only be called when an exponentiation with an integer
686  exponent is performed, thus tests & code for fractional exponents were
687  removed.
688  */
689 
690 double powi( double x, long int n ) /* returns: x^n */
691 /* x; base */
692 /* n; exponent */
693 {
694  double p; /* holds partial product */
695 
696  DEBUG_ENTRY( "powi()" );
697 
698  if( x == 0 )
699  return 0.;
700 
701  /* test for negative exponent */
702  if( n < 0 )
703  {
704  n = -n;
705  x = 1/x;
706  }
707 
708  p = is_odd(n) ? x : 1; /* test & set zero power */
709 
710  /*lint -e704 shift right of signed quantity */
711  /*lint -e720 Boolean test of assignment */
712  while( n >>= 1 )
713  { /* now do the other powers */
714  x *= x; /* sq previous power of x */
715  if( is_odd(n) ) /* if low order bit set */
716  p *= x; /* then, multiply partial product by latest power of x */
717  }
718  /*lint +e704 shift right of signed quantity */
719  /*lint +e720 Boolean test of assignment */
720  return p;
721 }
722 
723 #endif /* HAVE_POWI */
724 
725 /* efficiently calculate x^(p/q) */
726 double powpq(double x, int p, int q)
727 {
728  DEBUG_ENTRY( "powpq()" );
729 
730  if( q < 0 )
731  {
732  p = -p;
733  q = -q;
734  }
735 
736  if( q == 1 )
737  return powi(x,p);
738  else if( q == 2 )
739  return powi(sqrt(x),p);
740  else if( q == 3 )
741  return powi(cbrt(x),p);
742  else if( q == 4 )
743  return powi(sqrt(sqrt(x)),p);
744  else if( q == 6 )
745  return powi(sqrt(cbrt(x)),p);
746  else if( q == 8 )
747  return powi(sqrt(sqrt(sqrt(x))),p);
748  else if( q == 9 )
749  return powi(cbrt(cbrt(x)),p);
750  else
751  return pow(x,double(p)/double(q));
752 }
753 
754 long ipow( long m, long n ) /* returns: m^n */
755 /* m; base */
756 /* n; exponent */
757 {
758  long p; /* holds partial product */
759 
760  DEBUG_ENTRY( "ipow()" );
761 
762  if( m == 0 || (n < 0 && m > 1) )
763  return 0L;
764  /* NOTE: negative exponent always results in 0 for integers!
765  * (except for the case when m==1 or -1) */
766 
767  if( n < 0 )
768  { /* test for negative exponent */
769  n = -n;
770  m = 1/m;
771  }
772 
773  p = is_odd(n) ? m : 1; /* test & set zero power */
774 
775  /*lint -e704 shift right of signed quantity */
776  /*lint -e720 Boolean test of assignment */
777  while( n >>= 1 )
778  { /* now do the other powers */
779  m *= m; /* sq previous power of m */
780  if( is_odd(n) ) /* if low order bit set */
781  p *= m; /* then, multiply partial product by latest power of m */
782  }
783  /*lint +e704 shift right of signed quantity */
784  /*lint +e720 Boolean test of assignment */
785  return p;
786 }
787 
788 #ifndef HAVE_STRNLEN
789 
790 // this routine cannot clash with library version since it has C++ linkage
791 size_t strnlen(const char *s, size_t maxlen)
792 {
793  for( size_t i=0; i < maxlen; ++i )
794  if( s[i] == '\0' )
795  return i;
796  return maxlen;
797 }
798 
799 #endif
800 
801 //
802 // sncatf() is fully equivalent to snprintf() apart from the fact that it
803 // concatenates the output to an existing string rather than replacing it.
804 //
805 // this routine was taken from
806 // http://stackoverflow.com/questions/2674312/how-to-append-strings-using-sprintf
807 //
808 // the return value is the length the string in buf[] would have had _if_ buf[]
809 // would have been large enough to hold it. Hence this value can be used to test
810 // for truncation: if ret_val >= bufSize then the string in buf[] was truncated.
811 //
812 size_t sncatf( char* buf, size_t bufSize, const char* fmt, ... )
813 {
814  size_t result;
815  va_list args;
816  size_t len = strnlen( buf, bufSize );
817 
818  va_start( args, fmt );
819  result = vsnprintf( buf + len, bufSize - len, fmt, args );
820  va_end( args );
821 
822  return result + len;
823 }
824 
825 size_t sncatf( ostringstream& str, const char* fmt, ... )
826 {
827  DEBUG_ENTRY( "sncatf()" );
828  size_t result;
829  size_t len = str.tellp();
830  va_list args;
831  char tmp[64];
832  char *tmp1=tmp;
833 
834  va_start( args, fmt );
835  result = vsnprintf( tmp, sizeof(tmp), fmt, args );
836  va_end( args );
837 
838  if (result >= sizeof(tmp))
839  {
840  tmp1 = new char[result+1];
841  va_start( args, fmt );
842  result = vsnprintf( tmp1, result+1, fmt, args );
843  va_end( args );
844  }
845 
846  str << tmp1;
847 
848  if (tmp1 != tmp)
849  delete [] tmp1;
850 
851  return result+len;
852 }
853 
854 /*PrintE82 - series of routines to mimic 1p, e8.2 fortran output */
855 /***********************************************************
856  * contains the following sets of routines to get around *
857  * the MS C++ compilers unusual exponential output. *
858  * PrintEfmt <= much faster, no overhead with unix *
859  * PrintE93 *
860  * PrintE82 *
861  * PrintE71 *
862  **********************************************************/
863 
864 #ifdef _MSC_VER
865 /**********************************************************/
866 /*
867  * Instead of printf'ing with %e or %.5e or whatever, call
868  * efmt("%e", val) and print the result with %s. This lets
869  * us work around bugs in VS C 6.0.
870  */
871 char *PrintEfmt(const char *fmt, double val /* , char *buf */)
872 {
873  static char buf[30]; /* or pass it in */
874 
875  DEBUG_ENTRY( "PrintEfmt()" );
876 
877  /* create the string */
878  sprintf(buf, fmt, val);
879 
880  /* code to fix incorrect ms v e format. works only for case where there is
881  * a leading space in the format - for formats like 7.1, 8.2, 9.3, 10.4, etc
882  * result will have 1 too many characters */
883  char *ep , buf2[30];
884 
885  /* msvc behaves badly in different ways for positive vs negative sign vals,
886  * if val is positive must create a leading space */
887  if( val >= 0.)
888  {
889  strcpy(buf2 , " " );
890  strcat(buf2 , buf);
891  strcpy( buf , buf2);
892  }
893 
894  /* allow for both e and E formats */
895  if((ep = strchr_s(buf, 'e')) == NULL)
896  {
897  ep = strchr_s(buf, 'E');
898  }
899 
900  /* ep can still be NULL if val is Inf or NaN */
901  if(ep != NULL)
902  {
903  /* move pointer two char past the e, to pick up the e and sign */
904  ep += 2;
905 
906  /* terminate buf where the e is, *ep points to this location */
907  *ep = '\0';
908 
909  /* skip next char, */
910  ++ep;
911 
912  /* copy resulting string to return string */
913  strcat( buf, ep );
914  }
915  return buf;
916 }
917 #endif
918 
919 /**********************************************************/
920 void PrintE82( FILE* ioOUT, double value )
921 {
922  double frac , xlog , xfloor , tvalue;
923  int iExp;
924 
925  DEBUG_ENTRY( "PrintE82()" );
926 
927  if( value < 0 )
928  {
929  fprintf(ioOUT,"********");
930  }
931  else if( value <= DBL_MIN )
932  {
933  fprintf(ioOUT,"0.00E+00");
934  }
935  else
936  {
937  /* round number off for 8.2 format (not needed since can't be negative) */
938  tvalue = value;
939  xlog = log10( tvalue );
940  xfloor = floor(xlog);
941  /* this is now the fractional part */
942  if (xfloor < 0.)
943  frac = tvalue*exp10(-xfloor);
944  else
945  frac = (10.*tvalue)*exp10(-(xfloor+1.));
946  /*this is the possibly signed exponential part */
947  iExp = (int)xfloor;
948  if( frac>9.9945 )
949  {
950  frac /= 10.;
951  iExp += 1;
952  }
953  /* print the fractional part*/
954  fprintf(ioOUT,"%.2f",frac);
955  /* E for exponent */
956  fprintf(ioOUT,"E");
957  /* if positive throw a + sign*/
958  if(iExp>=0 )
959  {
960  fprintf(ioOUT,"+");
961  }
962  fprintf(ioOUT,"%.2d",iExp);
963  }
964  return;
965 }
966 /*
967  *==============================================================================
968  */
969 void PrintE71( FILE* ioOUT, double value )
970 {
971  double frac , xlog , xfloor , tvalue;
972  int iExp;
973 
974  DEBUG_ENTRY( "PrintE71()" );
975 
976  if( value < 0 )
977  {
978  fprintf(ioOUT,"*******");
979  }
980  else if( value <= DBL_MIN )
981  {
982  fprintf(ioOUT,"0.0E+00");
983  }
984  else
985  {
986  /* round number off for 8.2 format (not needed since can't be negative) */
987  tvalue = value;
988  xlog = log10( tvalue );
989  xfloor = floor(xlog);
990  /* this is now the fractional part */
991  if (xfloor < 0.)
992  frac = tvalue*exp10(-xfloor);
993  else
994  frac = (10.*tvalue)*exp10(-(xfloor+1.));
995  /*this is the possibly signed exponential part */
996  iExp = (int)xfloor;
997  if( frac>9.9945 )
998  {
999  frac /= 10.;
1000  iExp += 1;
1001  }
1002  /* print the fractional part*/
1003  fprintf(ioOUT,"%.1f",frac);
1004  /* E for exponent */
1005  fprintf(ioOUT,"E");
1006  /* if positive throw a + sign*/
1007  if(iExp>=0 )
1008  {
1009  fprintf(ioOUT,"+");
1010  }
1011  fprintf(ioOUT,"%.2d",iExp);
1012  }
1013  return;
1014 }
1015 
1016 /*
1017  *==============================================================================
1018  */
1019 void PrintE93( FILE* ioOUT, double value )
1020 {
1021  double frac , xlog , xfloor, tvalue;
1022  int iExp;
1023 
1024  DEBUG_ENTRY( "PrintE93()" );
1025 
1026  if( value < 0 )
1027  {
1028  fprintf(ioOUT,"*********");
1029  }
1030  else if( value <= DBL_MIN )
1031  {
1032  fprintf(ioOUT,"0.000E+00");
1033  }
1034  else
1035  {
1036  /* round number off for 9.3 format, neg numb not possible */
1037  tvalue = value;
1038  xlog = log10( tvalue );
1039  xfloor = floor(xlog);
1040  /* this is now the fractional part */
1041  if (xfloor < 0.)
1042  frac = tvalue*exp10(-xfloor);
1043  else
1044  frac = (10.*tvalue)*exp10(-(xfloor+1.));
1045  /*this is the possibly signed exponential part */
1046  iExp = (int)xfloor;
1047  if( frac>9.99949 )
1048  {
1049  frac /= 10.;
1050  iExp += 1;
1051  }
1052  /* print the fractional part*/
1053  fprintf(ioOUT,"%5.3f",frac);
1054  /* E for exponent */
1055  fprintf(ioOUT,"E");
1056  /* if positive throw a + sign*/
1057  if(iExp>=0 )
1058  {
1059  fprintf(ioOUT,"+");
1060  }
1061  fprintf(ioOUT,"%.2d",iExp);
1062  }
1063  return;
1064 }
1065 
1066 /*TotalInsanity general error handler for something that cannot happen */
1068 {
1069  DEBUG_ENTRY( "TotalInsanity()" );
1070 
1071  /* something that cannot happen, happened,
1072  * if this message is triggered, simply place a breakpoint here
1073  * and debug the error */
1074  fprintf( ioQQQ, " Something that cannot happen, has happened.\n" );
1075  fprintf( ioQQQ, " This is TotalInsanity, I live in %s.\n", __FILE__ );
1076  ShowMe();
1077 
1079 }
1080 
1081 /*BadRead general error handler for trying to read data, but failing */
1082 NORETURN void BadRead(void)
1083 {
1084  DEBUG_ENTRY( "BadRead()" );
1085 
1086  /* read failed */
1087  fprintf( ioQQQ, " A read of internal input data has failed.\n" );
1088  fprintf( ioQQQ, " This is BadRead, I live in %s.\n", __FILE__ );
1089  ShowMe();
1090 
1092 }
1093 
1094 /*sexp safe exponential function */
1096 {
1097  sys_float sexp_v;
1098 
1099  DEBUG_ENTRY( "sexp()" );
1100 
1101  /* SEXP_LIMIT is 84 in cddefines.h */
1102  if( x < SEXP_LIMIT )
1103  {
1104  sexp_v = exp(-x);
1105  }
1106  else
1107  {
1108  sexp_v = 0.f;
1109  }
1110  return sexp_v;
1111 }
1112 
1113 /*sexp safe exponential function */
1114 double sexp(double x)
1115 {
1116  double sexp_v;
1117 
1118  DEBUG_ENTRY( "sexp()" );
1119 
1120  /* SEXP_LIMIT is 84 in cddefines.h */
1121  if( x < SEXP_LIMIT )
1122  {
1123  sexp_v = exp(-x);
1124  }
1125  else
1126  {
1127  sexp_v = 0.;
1128  }
1129  return sexp_v;
1130 }
1131 
1132 
1133 /*dsexp safe exponential function for doubles */
1134 double dsexp(double x)
1135 {
1136  double dsexp_v;
1137 
1138  DEBUG_ENTRY( "dsexp()" );
1139 
1140  if( x < DSEXP_LIMIT )
1141  {
1142  dsexp_v = exp(-x);
1143  }
1144  else
1145  {
1146  dsexp_v = 0.;
1147  }
1148  return dsexp_v;
1149 }
1150 
1151 /*TestCode set flag saying that test code is in place
1152  * prototype in cddefines.h */
1153 void TestCode(void)
1154 {
1155  DEBUG_ENTRY( "TestCode()" );
1156 
1157  /* called if test code is in place */
1158  lgTestCodeCalled = true;
1159  return;
1160 }
1161 
1162 /*broken set flag saying that the code is broken, */
1163 void broken(void)
1164 {
1165  DEBUG_ENTRY( "broken()" );
1166 
1167  broke.lgBroke = true;
1168  return;
1169 }
1170 
1171 /*fixit say that code needs to be fixed */
1172 void fixit_base(const char* func,
1173  const char* file,
1174  int line,
1175  const char* reason
1176  )
1177 {
1178  DEBUG_ENTRY( "fixit_base()" );
1179 
1180  broke.lgFixit = true;
1181  ostringstream oss;
1182  oss << "-- At " << file << ":"<< line << " in " << func <<"()\n";
1183  oss << reason;
1184  FixitList::Inst().list.push_back(oss.str());
1185  return;
1186 }
1187 
1188 /*CodeReview placed next to code that needs to be checked */
1189 void CodeReview(void)
1190 {
1191  DEBUG_ENTRY( "CodeReview()" );
1192 
1193  broke.lgCheckit = true;
1194  return;
1195 }
1196 
1198 int dprintf(FILE *fp, const char *format, ...)
1199 {
1200  va_list ap;
1201  int i1, i2;
1202 
1203  DEBUG_ENTRY( "dprintf()" );
1204  va_start(ap,format);
1205  i1 = fprintf(fp,"DEBUG ");
1206  if (i1 >= 0)
1207  i2 = vfprintf(fp,format,ap);
1208  else
1209  i2 = 0;
1210  if (i2 < 0)
1211  i1 = 0;
1212  va_end(ap);
1213 
1214  return i1+i2;
1215 }
1216 
1217 int fprintf (const Output& stream, const char *format, ...)
1218 {
1219  va_list ap;
1220  va_start(ap,format);
1221  int i = vfprintf(stream.fptr(), format, ap);
1222  va_end(ap);
1223  return i;
1224 }
1225 
1226 int dprintf(const Output& stream, const char *format, ...)
1227 {
1228  DEBUG_ENTRY( "dprintf()" );
1229  va_list ap;
1230  va_start(ap,format);
1231  int i1 = fprintf(stream.fptr(),"DEBUG ");
1232  int i2;
1233  if (i1 >= 0)
1234  i2 = vfprintf(stream.fptr(),format,ap);
1235  else
1236  i2 = 0;
1237  if (i2 < 0)
1238  i1 = 0;
1239  va_end(ap);
1240 
1241  return i1+i2;
1242 }
1243 
1244 
1245 
1246 /* dbg_printf is a debug print routine that was provided by Peter Teuben,
1247  * as a component from his NEMO package. It offers run-time specification
1248  * of the level of debugging */
1249 int dbg_printf(int debug, const char *fmt, ...)
1250 {
1251  va_list ap;
1252  int i=0;
1253 
1254  DEBUG_ENTRY( "dbg_printf()" );
1255 
1256  /* print this debug message? (debug_level not currently used)*/
1257  if(debug <= trace.debug_level)
1258  {
1259  va_start(ap, fmt);
1260 
1261  i = vfprintf(ioQQQ, fmt, ap);
1262  /* drain ioQQQ */
1263  fflush(ioQQQ);
1264  va_end(ap);
1265  }
1266  return i;
1267 }
1268 
1269 
1270 /*qg32 32 point Gaussian quadrature, originally given to Gary F by Jim Lattimer */
1271 double qg32(
1272  double xl, /*lower limit to integration range*/
1273  double xu, /*upper limit to integration range*/
1274  /*following is the pointer to the function that will be evaluated*/
1275  double (*fct)(double) )
1276 {
1277  double a = 0.5*(xu+xl),
1278  b = xu-xl,
1279  y = 0.;
1280 
1281  DEBUG_ENTRY( "qg32()" );
1282 
1283  /********************************************************************************
1284  * *
1285  * 32-point Gaussian quadrature *
1286  * xl : the lower limit of integration *
1287  * xu : the upper limit *
1288  * fct : the (external) function *
1289  * returns the value of the integral *
1290  * *
1291  * simple call to integrate sine from 0 to pi *
1292  * double agn = qg32( 0., 3.141592654 , sin ); *
1293  * *
1294  *******************************************************************************/
1295 
1296  double weights[16] = {
1297  .35093050047350483e-2, .81371973654528350e-2, .12696032654631030e-1, .17136931456510717e-1,
1298  .21417949011113340e-1, .25499029631188088e-1, .29342046739267774e-1, .32911111388180923e-1,
1299  .36172897054424253e-1, .39096947893535153e-1, .41655962113473378e-1, .43826046502201906e-1,
1300  .45586939347881942e-1, .46922199540402283e-1, .47819360039637430e-1, .48270044257363900e-1};
1301 
1302  double c[16] = {
1303  .498631930924740780, .49280575577263417, .4823811277937532200, .46745303796886984000,
1304  .448160577883026060, .42468380686628499, .3972418979839712000, .36609105937014484000,
1305  .331522133465107600, .29385787862038116, .2534499544661147000, .21067563806531767000,
1306  .165934301141063820, .11964368112606854, .7223598079139825e-1, .24153832843869158e-1};
1307 
1308  for( int i=0; i<16; i++)
1309  {
1310  y += b * weights[i] * ((*fct)(a+b*c[i]) + (*fct)(a-b*c[i]));
1311  }
1312 
1313  /* the answer */
1314  return y;
1315 }
1316 
1317 /*spsort netlib routine to sort array returning sorted indices */
1318 void spsort(
1319  /* input array to be sorted */
1320  realnum x[],
1321  /* number of values in x */
1322  long int n,
1323  /* permutation output array */
1324  long int iperm[],
1325  /* flag saying what to do - 1 sorts into increasing order, not changing
1326  * the original vector, -1 sorts into decreasing order. 2, -2 change vector */
1327  int kflag,
1328  /* error condition, should be 0 */
1329  int *ier)
1330 {
1331  /*
1332  ****BEGIN PROLOGUE SPSORT
1333  ****PURPOSE Return the permutation vector generated by sorting a given
1334  * array and, optionally, rearrange the elements of the array.
1335  * The array may be sorted in increasing or decreasing order.
1336  * A slightly modified quicksort algorithm is used.
1337  ****LIBRARY SLATEC
1338  ****CATEGORY N6A1B, N6A2B
1339  ****TYPE SINGLE PRECISION (SPSORT-S, DPSORT-D, IPSORT-I, HPSORT-H)
1340  ****KEY WORDS NUMBER SORTING, PASSIVE SORTING, SINGLETON QUICKSORT, SORT
1341  ****AUTHOR Jones, R. E., (SNLA)
1342  * Rhoads, G. S., (NBS)
1343  * Wisniewski, J. A., (SNLA)
1344  ****DESCRIPTION
1345  *
1346  * SPSORT returns the permutation vector IPERM generated by sorting
1347  * the array X and, optionally, rearranges the values in X. X may
1348  * be sorted in increasing or decreasing order. A slightly modified
1349  * quicksort algorithm is used.
1350  *
1351  * IPERM is such that X(IPERM(I)) is the Ith value in the rearrangement
1352  * of X. IPERM may be applied to another array by calling IPPERM,
1353  * SPPERM, DPPERM or HPPERM.
1354  *
1355  * The main difference between SPSORT and its active sorting equivalent
1356  * SSORT is that the data are referenced indirectly rather than
1357  * directly. Therefore, SPSORT should require approximately twice as
1358  * long to execute as SSORT. However, SPSORT is more general.
1359  *
1360  * Description of Parameters
1361  * X - input/output -- real array of values to be sorted.
1362  * If ABS(KFLAG) = 2, then the values in X will be
1363  * rearranged on output; otherwise, they are unchanged.
1364  * N - input -- number of values in array X to be sorted.
1365  * IPERM - output -- permutation array such that IPERM(I) is the
1366  * index of the value in the original order of the
1367  * X array that is in the Ith location in the sorted
1368  * order.
1369  * KFLAG - input -- control parameter:
1370  * = 2 means return the permutation vector resulting from
1371  * sorting X in increasing order and sort X also.
1372  * = 1 means return the permutation vector resulting from
1373  * sorting X in increasing order and do not sort X.
1374  * = -1 means return the permutation vector resulting from
1375  * sorting X in decreasing order and do not sort X.
1376  * = -2 means return the permutation vector resulting from
1377  * sorting X in decreasing order and sort X also.
1378  * IER - output -- error indicator:
1379  * = 0 if no error,
1380  * = 1 if N is zero or negative,
1381  * = 2 if KFLAG is not 2, 1, -1, or -2.
1382  ****REFERENCES R. C. Singleton, Algorithm 347, An efficient algorithm
1383  * for sorting with minimal storage, Communications of
1384  * the ACM, 12, 3 (1969), pp. 185-187.
1385  ****ROUTINES CALLED XERMSG
1386  ****REVISION HISTORY (YYMMDD)
1387  * 761101 DATE WRITTEN
1388  * 761118 Modified by John A. Wisniewski to use the Singleton
1389  * quicksort algorithm.
1390  * 870423 Modified by Gregory S. Rhoads for passive sorting with the
1391  * option for the rearrangement of the original data.
1392  * 890620 Algorithm for rearranging the data vector corrected by R.
1393  * Boisvert.
1394  * 890622 Prologue upgraded to Version 4.0 style by D. Lozier.
1395  * 891128 Error when KFLAG.LT.0 and N=1 corrected by R. Boisvert.
1396  * 920507 Modified by M. McClain to revise prologue text.
1397  * 920818 Declarations section rebuilt and code restructured to use
1398  * IF-THEN-ELSE-ENDIF. (SMR, WRB)
1399  ****END PROLOGUE SPSORT
1400  * .. Scalar Arguments ..
1401  */
1402  long int i,
1403  ij,
1404  il[21],
1405  indx,
1406  indx0,
1407  istrt,
1408  istrt_,
1409  iu[21],
1410  j,
1411  k,
1412  kk,
1413  l,
1414  lm,
1415  lmt,
1416  m,
1417  nn;
1418  realnum r,
1419  ttemp;
1420 
1421  DEBUG_ENTRY( "spsort()" );
1422 
1423  /* .. Array Arguments .. */
1424  /* .. Local Scalars .. */
1425  /* .. Local Arrays .. */
1426  /* .. External Subroutines .. */
1427  /* .. Intrinsic Functions .. */
1428  /****FIRST EXECUTABLE STATEMENT SPSORT */
1429  *ier = 0;
1430  nn = n;
1431  if( nn < 1 )
1432  {
1433  *ier = 1;
1434  return;
1435  }
1436  else
1437  {
1438  kk = labs(kflag);
1439  if( kk != 1 && kk != 2 )
1440  {
1441  *ier = 2;
1442  return;
1443  }
1444  else
1445  {
1446 
1447  /* Initialize permutation vector to index on f scale
1448  * */
1449  for( i=0; i < nn; i++ )
1450  {
1451  iperm[i] = i+1;
1452  }
1453 
1454  /* Return if only one value is to be sorted */
1455  if( nn == 1 )
1456  {
1457  --iperm[0];
1458  return;
1459  }
1460 
1461  /* Alter array X to get decreasing order if needed */
1462  if( kflag <= -1 )
1463  {
1464  for( i=0; i < nn; i++ )
1465  {
1466  x[i] = -x[i];
1467  }
1468  }
1469 
1470  /* Sort X only */
1471  m = 1;
1472  i = 1;
1473  j = nn;
1474  r = .375e0;
1475  }
1476  }
1477 
1478  while( true )
1479  {
1480  if( i == j )
1481  goto L_80;
1482  if( r <= 0.5898437e0 )
1483  {
1484  r += 3.90625e-2;
1485  }
1486  else
1487  {
1488  r -= 0.21875e0;
1489  }
1490 
1491 L_40:
1492  k = i;
1493 
1494  /* Select a central element of the array and save it in location L
1495  * */
1496  ij = i + (long)((j-i)*r);
1497  lm = iperm[ij-1];
1498 
1499  /* If first element of array is greater than LM, interchange with LM
1500  * */
1501  if( x[iperm[i-1]-1] > x[lm-1] )
1502  {
1503  iperm[ij-1] = iperm[i-1];
1504  iperm[i-1] = lm;
1505  lm = iperm[ij-1];
1506  }
1507  l = j;
1508 
1509  /* If last element of array is less than LM, interchange with LM
1510  * */
1511  if( x[iperm[j-1]-1] < x[lm-1] )
1512  {
1513  iperm[ij-1] = iperm[j-1];
1514  iperm[j-1] = lm;
1515  lm = iperm[ij-1];
1516 
1517  /* If first element of array is greater than LM, interchange
1518  * with LM
1519  * */
1520  if( x[iperm[i-1]-1] > x[lm-1] )
1521  {
1522  iperm[ij-1] = iperm[i-1];
1523  iperm[i-1] = lm;
1524  lm = iperm[ij-1];
1525  }
1526  }
1527 
1528  /* Find an element in the second half of the array which is smaller
1529  * than LM */
1530  while( true )
1531  {
1532  l -= 1;
1533  if( x[iperm[l-1]-1] <= x[lm-1] )
1534  {
1535 
1536  /* Find an element in the first half of the array which is greater
1537  * than LM */
1538  while( true )
1539  {
1540  k += 1;
1541  if( x[iperm[k-1]-1] >= x[lm-1] )
1542  break;
1543  }
1544 
1545  /* Interchange these elements */
1546  if( k > l )
1547  break;
1548  lmt = iperm[l-1];
1549  iperm[l-1] = iperm[k-1];
1550  iperm[k-1] = lmt;
1551  }
1552  }
1553 
1554  /* Save upper and lower subscripts of the array yet to be sorted */
1555  if( l - i > j - k )
1556  {
1557  il[m-1] = i;
1558  iu[m-1] = l;
1559  i = k;
1560  m += 1;
1561  }
1562  else
1563  {
1564  il[m-1] = k;
1565  iu[m-1] = j;
1566  j = l;
1567  m += 1;
1568  }
1569 
1570 L_90:
1571  if( j - i >= 1 )
1572  goto L_40;
1573  if( i == 1 )
1574  continue;
1575  i -= 1;
1576 
1577  while( true )
1578  {
1579  i += 1;
1580  if( i == j )
1581  break;
1582  lm = iperm[i];
1583  if( x[iperm[i-1]-1] > x[lm-1] )
1584  {
1585  k = i;
1586 
1587  while( true )
1588  {
1589  iperm[k] = iperm[k-1];
1590  k -= 1;
1591 
1592  if( x[lm-1] >= x[iperm[k-1]-1] )
1593  break;
1594  }
1595  iperm[k] = lm;
1596  }
1597  }
1598 
1599  /* Begin again on another portion of the unsorted array */
1600 L_80:
1601  m -= 1;
1602  if( m == 0 )
1603  break;
1604  /*lint -e644 not explicitly initialized */
1605  i = il[m-1];
1606  j = iu[m-1];
1607  /*lint +e644 not explicitly initialized */
1608  goto L_90;
1609  }
1610 
1611  /* Clean up */
1612  if( kflag <= -1 )
1613  {
1614  for( i=0; i < nn; i++ )
1615  {
1616  x[i] = -x[i];
1617  }
1618  }
1619 
1620  /* Rearrange the values of X if desired */
1621  if( kk == 2 )
1622  {
1623 
1624  /* Use the IPERM vector as a flag.
1625  * If IPERM(I) < 0, then the I-th value is in correct location */
1626  for( istrt=1; istrt <= nn; istrt++ )
1627  {
1628  istrt_ = istrt - 1;
1629  if( iperm[istrt_] >= 0 )
1630  {
1631  indx = istrt;
1632  indx0 = indx;
1633  ttemp = x[istrt_];
1634  while( iperm[indx-1] > 0 )
1635  {
1636  x[indx-1] = x[iperm[indx-1]-1];
1637  indx0 = indx;
1638  iperm[indx-1] = -iperm[indx-1];
1639  indx = labs(iperm[indx-1]);
1640  }
1641  x[indx0-1] = ttemp;
1642  }
1643  }
1644 
1645  /* Revert the signs of the IPERM values */
1646  for( i=0; i < nn; i++ )
1647  {
1648  iperm[i] = -iperm[i];
1649  }
1650  }
1651 
1652  for( i=0; i < nn; i++ )
1653  {
1654  --iperm[i];
1655  }
1656  return;
1657 }
1658 
1659 /*MyMalloc wrapper for malloc(). Returns a good pointer or dies.
1660  * memory is filled with NaN
1661  * >>chng 05 dec 14, do not set to NaN since tricks debugger
1662  * routines within code do not call this or malloc, but rather MALLOC
1663  * which is resolved into MyMalloc or malloc depending on whether
1664  * NDEBUG is set by the compiler to indicate "not debugging",
1665  * in typical negative C style */
1666 STATIC void MyMalloc_base(void* ptr,
1667  size_t size, /*use same type as library function MALLOC*/
1668  const char *chFile,
1669  int line)
1670 {
1671  DEBUG_ENTRY( "MyMalloc_base()" );
1672 
1673  /* debug branch for printing malloc args */
1674  {
1675  enum{DEBUG_LOC=false};
1676  if( DEBUG_LOC)
1677  {
1678  static long int kount=0, nTot=0;
1679  nTot += (long)size;
1680  fprintf(ioQQQ,"%li\t%li\t%li\n",
1681  kount ,
1682  (long)size ,
1683  nTot );
1684  ++kount;
1685  }
1686  }
1687 
1688  if( ptr == NULL )
1689  {
1690  fprintf(ioQQQ,"DISASTER MyMalloc could not allocate %lu bytes. Exit in MyMalloc.",
1691  (unsigned long)size );
1692  fprintf(ioQQQ,"MyMalloc called from file %s at line %i.\n",
1693  chFile , line );
1694 
1695  if( struc.nzlim>2000 )
1696  fprintf(ioQQQ,"This may have been caused by the large number of zones."
1697  " %li zones were requested. Is this many zones really necessary?\n",
1698  struc.nzlim );
1699 
1701  }
1702 
1703  /* flag -DNOINIT will turn off this initialization which can fool valgrind/purify */
1704 # if !defined(NDEBUG) && !defined(NOINIT)
1705 
1706  size_t nFloat = size/4;
1707  size_t nDouble = size/8;
1708  sys_float *fptr = static_cast<sys_float*>(ptr);
1709  double *dptr = static_cast<double*>(ptr);
1710 
1711  /* >>chng 04 feb 03, fill memory with invalid numbers, PvH */
1712  /* on IA32/AMD64 processors this will generate NaN's for both float and double;
1713  * on most other (modern) architectures it is likely to do the same... */
1714  /* >>chng 05 dec 14, change code to generate signaling NaN's for most cases (but not all!) */
1715  if( size == nDouble*8 )
1716  {
1717  /* this could be an array of doubles as well as floats -> we will hedge our bets
1718  * we will fill the array with a pattern that is interpreted as all signaling
1719  * NaN's for doubles, and alternating signaling and quiet NaN's for floats:
1720  * byte offset: 0 4 8 12 16
1721  * double | SNaN | SNan |
1722  * float | SNaN | QNaN | SNan | QNaN | (little-endian, e.g. Intel, AMD, alpha)
1723  * float | QNaN | SNaN | QNan | SNaN | (big-endian, e.g. Sparc, PowerPC, MIPS) */
1724  set_NaN( dptr, (long)nDouble );
1725  }
1726  else if( size == nFloat*4 )
1727  {
1728  /* this could be an arrays of floats, but not doubles -> init to all float SNaN */
1729  set_NaN( fptr, (long)nFloat );
1730  }
1731  else
1732  {
1733  memset( ptr, 0xff, size );
1734  }
1735 
1736 # endif /* !defined(NDEBUG) && !defined(NOINIT) */
1737 }
1738 
1739 void *MyMalloc(size_t size,
1740  const char *chFile,
1741  int line)
1742 {
1743  ASSERT( size > 0 );
1744 
1745  void *ptr = malloc(size);
1746  MyMalloc_base(ptr, size, chFile, line);
1747  return ptr;
1748 }
1749 
1750 void *MyMalloc_avx(size_t size,
1751  const char *chFile,
1752  int line)
1753 {
1754  ASSERT( size > 0 );
1755 
1756  void *ptr;
1757  if( posix_memalign(&ptr, CD_ALIGN, size) != 0 )
1758  ptr = NULL;
1759  MyMalloc_base(ptr, size, chFile, line);
1760  return ptr;
1761 }
1762 
1763 /* function to facilitate addressing opacity array */
1764 double csphot(
1765  /* INU is array index pointing to frequency where opacity is to be evaluated
1766  * on f not c scale */
1767  long int inu,
1768  /* ITHR is pointer to threshold*/
1769  long int ithr,
1770  /* IOFSET is offset as defined in opac0*/
1771  long int iofset)
1772 {
1773  double csphot_v;
1774 
1775  DEBUG_ENTRY( "csphot()" );
1776 
1777  csphot_v = opac.OpacStack[inu-ithr+iofset-1];
1778  return csphot_v;
1779 }
1780 
1781 /*RandGauss normal Gaussian random number generator
1782  * the user must call srand to set the seed before using this routine.
1783 
1784  * the random numbers will have a mean of xMean and a standard deviation of s
1785 
1786  * The convention is for srand to be called when the command setting
1787  * the noise is parsed
1788 
1789  * for very small dispersion there are no issues, but when the dispersion becomes
1790  * large the routine will find negative values - so most often used in this case
1791  * to find dispersion in log space
1792  * this routine will return a normal Gaussian - must be careful in how this is
1793  * used when adding noise to physical quantity */
1794 /*
1795 NB - following from Ryan Porter:
1796 I discovered that I unintentionally created an antisymmetric skew in my
1797 Monte Carlo. RandGauss is symmetric in log space, which means it is not
1798 symmetric in linear space. But to get the right standard deviation you
1799 have to take 10^x, where x is the return from RandGauss. The problem is
1800 10^x will happen less frequently than 10^-x, so without realizing it, the
1801 average "tweak" to every piece of atomic data in my Monte Carlo run was
1802 not 1.0 but something greater than 1.0, causing every single line to have
1803 an average Monte Carlo emissivity greater than the regular value. Any place
1804 that takes 10^RandGauss() needs to be adjusted if what is intended is +/- x. */
1805 double RandGauss(
1806  /* mean value */
1807  double xMean,
1808  /*standard deviation s */
1809  double s )
1810 {
1811  double x1, x2, w, yy1;
1812  static double yy2=-BIGDOUBLE;
1813  static int use_last = false;
1814 
1815  DEBUG_ENTRY( "RandGauss()" );
1816 
1817  if( use_last )
1818  {
1819  yy1 = yy2;
1820  use_last = false;
1821  }
1822  else
1823  {
1824  do {
1825  x1 = 2.*genrand_real3() - 1.;
1826  x2 = 2.*genrand_real3() - 1.;
1827  w = x1 * x1 + x2 * x2;
1828  } while ( w >= 1.0 );
1829 
1830  w = sqrt((-2.0*log(w))/w);
1831  yy1 = x1 * w;
1832  yy2 = x2 * w;
1833  use_last = true;
1834  }
1835  return xMean + yy1 * s;
1836 }
1837 
1838 /* MyGaussRand takes as input a percent uncertainty less than 50%
1839  * (expressed as 0.5). The routine then assumes this input variable represents one
1840  * standard deviation about a mean of unity, and returns a random number within
1841  * that range. A hard cutoff is imposed at two standard deviations, which
1842  * eliminates roughly 5% of the normal distribution. In other words, the routine
1843  * returns a number in a normal distribution with standard deviation equal to
1844  * the input. The number will be between 1-3*stdev and 1+3*stdev. */
1845 double MyGaussRand( double PctUncertainty )
1846 {
1847  double StdDev;
1848  double result;
1849 
1850  DEBUG_ENTRY( "MyGaussRand()" );
1851 
1852  ASSERT( PctUncertainty < 0.5 );
1853  /* We want this "percent uncertainty" to represent one standard deviation */
1854  StdDev = PctUncertainty;
1855 
1856  do
1857  {
1858  /*result = exp10( RandGauss( 0., logStdDev ) );*/
1859  result = 1.+RandGauss( 0., StdDev );
1860  }
1861  /* only allow values that are within 3 standard deviations */
1862  while( (result < 1.-3.*PctUncertainty) || (result > 1.+3.*PctUncertainty) );
1863 
1864  ASSERT( result>0. && result<2. );
1865  return result;
1866 }
1867 
1868 /*plankf evaluate Planck function for any cell at current electron temperature */
1869 double plankf(long int ip)
1870 {
1871  double plankf_v;
1872 
1873  DEBUG_ENTRY( "plankf()" );
1874 
1875  /* evaluate Planck function
1876  * argument is pointer to cell energy in ANU
1877  * return photon flux for cell IP */
1878  if( rfield.ContBoltz[ip] <= 0. )
1879  {
1880  plankf_v = 1e-35;
1881  }
1882  else
1883  {
1884  plankf_v = 6.991e-21*POW2(FR1RYD*rfield.anu(ip))/
1885  (1./rfield.ContBoltz[ip] - 1.)*FR1RYD*4.;
1886  }
1887  return plankf_v;
1888 }
1889 
1891 {
1892  fstream io;
1893  string line;
1894  open_data( io, "citation_cloudy.txt", mode_r );
1895  while( SafeGetline( io, line ) )
1896  {
1897  if( line[0] == '#' )
1898  continue;
1899  // replace XXXX with actual version number
1900  size_t p = line.find( "XXXX" );
1901  if( p != string::npos )
1902  line.replace( p, 4, t_version::Inst().chVersion );
1903  fprintf( ioQQQ, "%s\n", line.c_str() );
1904  }
1905 }
1906 
1908 {
1909  fstream io;
1910  string line;
1911  open_data( io, "citation_data.txt", mode_r );
1912  while( SafeGetline( io, line ) )
1913  {
1914  if( line[0] == '#' )
1915  continue;
1916  // replace XXXX with actual version number
1917  size_t p = line.find( "XXXX" );
1918  if( p != string::npos )
1919  line.replace( p, 4, atmdat.chVersion );
1920  fprintf( ioQQQ, "%s\n", line.c_str() );
1921  }
1922 }
1923 
1924 // this routine was taken from
1925 // http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf
1926 // it is copyrighted by a creative commons license
1927 // http://creativecommons.org/licenses/by-sa/3.0/
1928 //
1929 // safe version of getline() that correctly handles all types of EOL lf, crlf and cr...
1930 // it has been modified such that it does not produce a spurious empty line at the end of a file
1931 // this way it is compatible with the standard getline() (at least with g++/linux).
1932 istream& SafeGetline(istream& is, string& t)
1933 {
1934  t.clear();
1935 
1936  // The characters in the stream are read one-by-one using a streambuf.
1937  // That is faster than reading them one-by-one using the istream.
1938  // Code that uses streambuf this way must be guarded by a sentry object.
1939  // The sentry object performs various tasks,
1940  // such as thread synchronization and updating the stream state.
1941 
1942  istream::sentry se(is, true);
1943  streambuf* sb = is.rdbuf();
1944 
1945  while( true )
1946  {
1947  int c = sb->sbumpc();
1948  switch (c)
1949  {
1950  case '\n':
1951  if( sb->sgetc() == EOF )
1952  is.setstate(ios::eofbit);
1953  return is;
1954  case '\r':
1955  if( sb->sgetc() == '\n' )
1956  sb->sbumpc();
1957  if( sb->sgetc() == EOF )
1958  is.setstate(ios::eofbit);
1959  return is;
1960  case EOF:
1961  // Also handle the case when the last line has no line ending
1962  is.setstate(ios::eofbit);
1963  return is;
1964  default:
1965  t += (char)c;
1966  }
1967  }
1968 }
long int nTeFail
Definition: conv.h:203
t_fudgec fudgec
Definition: fudgec.cpp:5
FILE * open_data(const char *fname, const char *mode, access_scheme scheme)
Definition: cpu.cpp:751
t_atmdat atmdat
Definition: atmdat.cpp:6
void cdPrintCommands(FILE *ioOUT)
Definition: cddrive.cpp:532
void PrintE93(FILE *, double)
Definition: service.cpp:1019
static double x2[63]
bool is_odd(int j)
Definition: cddefines.h:757
double * OpacStack
Definition: opacity.h:163
double exp10(double x)
Definition: cddefines.h:1383
#define NORETURN
Definition: cpu.h:451
istream & SafeGetline(istream &is, string &t)
Definition: service.cpp:1932
NORETURN void TotalInsanity(void)
Definition: service.cpp:1067
t_input input
Definition: input.cpp:12
const double BIGDOUBLE
Definition: cpu.h:249
static const double neg_pow10[]
Definition: service.cpp:356
t_opac opac
Definition: opacity.cpp:5
static double x1[83]
t_struc struc
Definition: struc.cpp:6
split_mode
Definition: service.h:16
void set_NaN(sys_float &x)
Definition: cpu.cpp:862
long int nSaveIni
Definition: input.h:62
static const double pos_pow10[]
Definition: service.cpp:320
size_t sncatf(char *buf, size_t bufSize, const char *fmt,...)
Definition: service.cpp:812
bool lgFudgeUsed
Definition: fudgec.h:19
void cdCautions(FILE *ioOUT)
Definition: cddrive.cpp:220
char TorF(bool l)
Definition: cddefines.h:753
#define PrintEfmt(F, V)
Definition: cddefines.h:1364
bool lgBroke
Definition: broke.h:30
t_warnings warnings
Definition: warnings.cpp:11
void cdWarnings(FILE *ioPNT)
Definition: cddrive.cpp:192
long nMatch(const char *chKey, const char *chCard)
Definition: service.cpp:537
t_conv conv
Definition: conv.cpp:5
T sign(T x, T y)
Definition: cddefines.h:846
t_hextra hextra
Definition: hextra.cpp:5
static const int max_pow10
Definition: service.cpp:354
const char * strstr_s(const char *haystack, const char *needle)
Definition: cddefines.h:1315
void * MyMalloc(size_t size, const char *file, int line)
Definition: service.cpp:1739
sys_float sexp(sys_float x)
Definition: service.cpp:1095
int dbg_printf(int debug, const char *fmt,...)
Definition: service.cpp:1249
double fudge(long int ipnt)
Definition: service.cpp:567
FILE * ioQQQ
Definition: cddefines.cpp:7
long int ncaun
Definition: warnings.h:28
molezone * findspecieslocal(const char buf[])
long int nzone
Definition: cddefines.cpp:14
bool lgTalk
Definition: called.h:12
Definition: mole.h:378
void CloudyPrintReference()
Definition: service.cpp:1890
void cap4(char *chCAP, const char *chLab)
Definition: service.cpp:264
double anu(size_t i) const
Definition: mesh.h:111
double dsexp(double x)
Definition: service.cpp:1134
void CodeReview(void)
Definition: service.cpp:1189
void trimTrailingWhiteSpace(string &str)
Definition: service.cpp:155
void fixit_base(const char *func, const char *file, int line, const char *reason)
Definition: service.cpp:1172
char chVersion[iVersionLength]
Definition: atmdat.h:448
static t_version & Inst()
Definition: cddefines.h:209
realnum xFracLim
Definition: mole.h:424
void uncaps(char *chCard)
Definition: service.cpp:287
char toupper(char c)
Definition: cddefines.h:743
long int iteration
Definition: cddefines.cpp:16
const double DSEXP_LIMIT
Definition: cddefines.h:1370
bool lgSearch
Definition: conv.h:168
t_trace trace
Definition: trace.cpp:5
int GetQuote(char *chLabel, char *chCard, char *chCardRaw, bool lgABORT)
Definition: service.cpp:599
void broken(void)
Definition: service.cpp:1163
int dprintf(FILE *fp, const char *format,...)
Definition: service.cpp:1198
void PrintE71(FILE *, double)
Definition: service.cpp:969
char tolower(char c)
Definition: cddefines.h:734
const ios_base::openmode mode_r
Definition: cpu.h:267
#define POW2
Definition: cddefines.h:983
#define STATIC
Definition: cddefines.h:118
t_rfield rfield
Definition: rfield.cpp:9
float realnum
Definition: cddefines.h:124
#define EXIT_FAILURE
Definition: cddefines.h:168
float sys_float
Definition: cddefines.h:127
bool lgFixit
Definition: broke.h:33
#define cdEXIT(FAIL)
Definition: cddefines.h:484
t_broke broke
Definition: broke.cpp:10
size_t strnlen(const char *s, size_t maxlen)
Definition: service.cpp:791
double powi(double, long int)
Definition: service.cpp:690
double * ContBoltz
Definition: rfield.h:126
long min(int a, long b)
Definition: cddefines.h:766
const char * strchr_s(const char *s, int c)
Definition: cddefines.h:1325
diatomics h2("h2", 4100.,&hmi.H2_total, Yan_H2_CS)
void * MyMalloc_avx(size_t size, const char *file, int line)
Definition: service.cpp:1750
double RandGauss(double xMean, double s)
Definition: service.cpp:1805
realnum cryden
Definition: hextra.h:24
double AnuUnit(realnum energy)
Definition: service.cpp:197
void MyAssert(const char *file, int line, const char *comment)
Definition: service.cpp:177
long int nfudge
Definition: fudgec.h:17
long int nzlim
Definition: struc.h:19
long int ipow(long, long)
Definition: service.cpp:754
static const int min_pow10
Definition: service.cpp:390
#define ASSERT(exp)
Definition: cddefines.h:617
FILE * fptr() const
Definition: cddefines.h:233
double qg32(double, double, double(*)(double))
Definition: service.cpp:1271
double csphot(long int inu, long int ithr, long int iofset)
Definition: service.cpp:1764
Definition: energy.h:9
#define DEBUG_ENTRY(funcname)
Definition: cddefines.h:729
double powpq(double x, int p, int q)
Definition: service.cpp:726
STATIC void MyMalloc_base(void *ptr, size_t size, const char *chFile, int line)
Definition: service.cpp:1666
void DatabasePrintReference()
Definition: service.cpp:1907
bool lgTestCodeCalled
Definition: cddefines.cpp:11
int fprintf(const Output &stream, const char *format,...)
Definition: service.cpp:1217
const char * chConSavEnr[LIMPUN]
Definition: save.h:387
double pow(double x, int i)
Definition: cddefines.h:782
void Split(const string &str, const string &sep, vector< string > &lst, split_mode mode)
Definition: service.cpp:108
vector< string > list
Definition: broke.h:17
char * read_whole_line(char *chLine, int nChar, FILE *ioIN)
Definition: service.cpp:72
double MyGaussRand(double PctUncertainty)
Definition: service.cpp:1845
long int nwarn
Definition: warnings.h:28
int debug_level
Definition: trace.h:118
#define CD_ALIGN
Definition: cpu.h:156
void caps(char *chCard)
Definition: service.cpp:304
double fnzone
Definition: cddefines.cpp:15
void ShowMe(void)
Definition: service.cpp:205
void PrintE82(FILE *, double)
Definition: service.cpp:920
t_save save
Definition: save.cpp:5
double genrand_real3()
double frac(double d)
const double SEXP_LIMIT
Definition: cddefines.h:1368
double plankf(long int ip)
Definition: service.cpp:1869
long int ipConPun
Definition: save.h:390
void TestCode(void)
Definition: service.cpp:1153
double get(const char *unit) const
Definition: energy.cpp:138
t_called called
Definition: called.cpp:4
NORETURN void BadRead(void)
Definition: service.cpp:1082
bool lgAbort
Definition: cddefines.cpp:10
void spsort(realnum x[], long int n, long int iperm[], int kflag, int *ier)
Definition: service.cpp:1318
bool lgCheckit
Definition: broke.h:37
realnum fudgea[NFUDGC]
Definition: fudgec.h:15
double FFmtRead(const char *chCard, long int *ipnt, long int last, bool *lgEOL)
Definition: service.cpp:393