00001
00002
00004 #if defined(__HP_aCC)
00005
00006 extern "C" unsigned long fegettrapenable();
00007 extern "C" void fesettrapenable(unsigned long);
00008 #endif
00009
00010 #if defined(__ia64) && defined(__INTEL_COMPILER)
00011 extern "C" unsigned long fpgetmask();
00012 extern "C" void fpsetmask(unsigned long);
00013 #endif
00014
00015 #if defined(__sun) || defined(__sgi)
00016 #include <ieeefp.h>
00017 #if defined(HAVE_SUNMATH) || defined(FLUSH_DENORM_TO_ZERO)
00018 #include <sunmath.h>
00019 #endif
00020 #endif
00021
00022 #if defined(__alpha) && defined(__linux) && defined(__GNUC__)
00023 #define __USE_GNU
00024 #include <fenv.h>
00025 #endif
00026
00027 #ifdef __unix
00028 #include <unistd.h>
00029 #endif
00030
00031
00032
00033 #include "cddefines.h"
00034 #include "path.h"
00035 #include "trace.h"
00036
00037 STATIC NORETURN void AbortErrorMessage( const char* fname, vector<string>& PathList, access_scheme scheme );
00038
00039
00040 t_cpu::t_cpu()
00041 {
00042 DEBUG_ENTRY( "t_cpu()" );
00043
00044 #ifdef CATCH_SIGNAL
00045
00046
00047 # ifdef __unix
00048 p_action.sa_handler = &signal_handler;
00049 sigemptyset( &p_action.sa_mask );
00050 p_action.sa_flags = SA_NODEFER;
00051
00052 p_default.sa_handler = SIG_DFL;
00053 sigemptyset( &p_default.sa_mask );
00054 p_default.sa_flags = SA_NODEFER;
00055
00056 for( int sig=1; sig <= 31; sig++ )
00057 {
00058
00059 if( sigaction( sig, NULL, NULL ) == 0 )
00060
00061 if( sig != SIGSTOP && sig != SIGCONT )
00062 sigaction( sig, action(), NULL );
00063 }
00064 # endif
00065
00066 # ifdef _MSC_VER
00067 signal( SIGABRT, &signal_handler );
00068 signal( SIGFPE, &signal_handler );
00069 signal( SIGILL, &signal_handler );
00070 signal( SIGINT, &signal_handler );
00071 signal( SIGSEGV, &signal_handler );
00072 signal( SIGTERM, &signal_handler );
00073 # endif
00074 #endif
00075
00076
00077 endian.c[0] = 0x12;
00078 endian.c[1] = 0x34;
00079 endian.c[2] = 0x56;
00080 endian.c[3] = 0x78;
00081
00082
00083
00084 if( sizeof(sys_float) == 4 )
00085 {
00086 # ifdef __mips
00087
00088 Float_SNaN_Value = 0xffffffff;
00089 # else
00090 if( big_endian() || little_endian() )
00091 {
00092
00093 Float_SNaN_Value = 0xffbfffff;
00094 }
00095 else
00096 {
00097
00098 Float_SNaN_Value = -1;
00099 }
00100 # endif
00101 }
00102 else
00103 {
00104
00105 Float_SNaN_Value = -1;
00106 }
00107
00108 # ifdef HAVE_INT64
00109
00110 if( sizeof(double) == 8 )
00111 {
00112 # ifdef __mips
00113
00114 Double_SNaN_Value = 0xffffffffffffffff;
00115 # else
00116
00117 Double_SNaN_Value = 0xfff7ffffffbfffff;
00118 # endif
00119 }
00120 else
00121 {
00122
00123 Double_SNaN_Value = -1;
00124 }
00125
00126 # else
00127
00128 if( sizeof(double) == 8 )
00129 {
00130 # ifdef __mips
00131
00132 Double_SNaN_Value[0] = 0xffffffff;
00133 Double_SNaN_Value[1] = 0xffffffff;
00134 # else
00135 if( big_endian() )
00136 {
00137
00138 Double_SNaN_Value[0] = 0xfff7ffff;
00139 Double_SNaN_Value[1] = 0xffbfffff;
00140 }
00141 else if( little_endian() )
00142 {
00143
00144 Double_SNaN_Value[0] = 0xffbfffff;
00145 Double_SNaN_Value[1] = 0xfff7ffff;
00146 }
00147 else
00148 {
00149
00150 Double_SNaN_Value[0] = -1;
00151 Double_SNaN_Value[1] = -1;
00152 }
00153 # endif
00154 }
00155 else
00156 {
00157
00158 Double_SNaN_Value[0] = -1;
00159 Double_SNaN_Value[1] = -1;
00160 }
00161
00162 # endif
00163
00164
00165 enable_traps();
00166
00167 ioStdin = stdin;
00168 ioQQQ = stdout;
00169 ioPrnErr = stderr;
00170 lgPrnErr = false;
00171
00172 test_float = FLT_MIN;
00173 test_double = DBL_MIN;
00174
00175
00176 p_lgAssertAbort = false;
00177
00178 const char *str;
00179
00180
00181 # if defined(_SC_NPROCESSORS_ONLN)
00182 n_avail_CPU = sysconf(_SC_NPROCESSORS_ONLN);
00183 # elif defined(_SC_NPROC_ONLN)
00184 n_avail_CPU = sysconf(_SC_NPROC_ONLN);
00185 # elif defined(_SC_CRAY_NCPU)
00186 n_avail_CPU = sysconf(_SC_CRAY_NCPU);
00187 # elif defined(_WIN32)
00188 str = getenv( "NUMBER_OF_PROCESSORS" );
00189 if( str != NULL )
00190 {
00191 int found = sscanf( str, "%ld", &n_avail_CPU );
00192 if( found != 1 )
00193 n_avail_CPU = 1;
00194 }
00195 else
00196 {
00197 n_avail_CPU = 1;
00198 }
00199 # else
00200
00201 n_avail_CPU = 1;
00202 # endif
00203
00204 p_lgMPI = false;
00205
00206 p_lgMPISingleRankMode = false;
00207 n_rank = 0;
00208
00209 # ifdef _WIN32
00210 str = getenv( "COMPUTERNAME" );
00211 # else
00212 str = getenv( "HOSTNAME" );
00213 # endif
00214
00215 if( str != NULL )
00216 strncpy( HostName, str, STDLEN );
00217 else
00218 strncpy( HostName, "unknown", STDLEN );
00219 HostName[STDLEN-1] = '\0';
00220
00221
00222 const char *path = getenv( "CLOUDY_DATA_PATH" );
00223
00224
00225 string chSearchPathRaw = ( path != NULL ) ? string( path ) : string( CLOUDY_DATA_PATH );
00226
00227 # ifdef _WIN32
00228 string separator( ";" );
00229 char chExpectedEnd = '\\';
00230 # else
00231 string separator( ":" );
00232 char chExpectedEnd = '/';
00233 # endif
00234
00235 chSearchPath.push_back( "" );
00236 Split( chSearchPathRaw, separator, chSearchPath, SPM_RELAX );
00237 chSearchPath.push_back( "" );
00238
00239 for( vector<string>::size_type i=0; i < chSearchPath.size(); ++i )
00240 {
00241 if( chSearchPath[i].length() > 0 )
00242 {
00243
00244 char chEnd = *chSearchPath[i].rbegin();
00245
00246
00247 if( chEnd != chExpectedEnd )
00248 chSearchPath[i] += chExpectedEnd;
00249 }
00250 }
00251
00252 nFileDone = 0;
00253 }
00254
00255 void t_cpu::enable_traps() const
00256 {
00257
00258
00259
00260
00261
00262
00263
00264 # if defined(_MSC_VER)
00265 volatile unsigned int NewMask;
00266
00267
00268
00269
00270 NewMask = _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_INVALID;
00271
00272 NewMask = ~NewMask;
00273 _controlfp( NewMask , _MCW_EM );
00274
00275
00276
00277
00278 # elif defined(__GNUC__) && ( defined(__i386) || defined(__amd64) )
00279 volatile unsigned int Old_Mask, New_Mask;
00280 # if defined(__SSE__) || defined(__SSE2__)
00281 volatile unsigned int SSE_Mask;
00282 # endif
00283
00284 # define _FPU_MASK_IM 0x01
00285 # define _FPU_MASK_DM 0x02
00286 # define _FPU_MASK_ZM 0x04
00287 # define _FPU_MASK_OM 0x08
00288 # define _FPU_MASK_UM 0x10
00289 # define _FPU_MASK_PM 0x20
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 volatile unsigned int UnMask = ~((unsigned int)( _FPU_MASK_ZM | _FPU_MASK_IM | _FPU_MASK_OM ));
00300
00301 __asm__ volatile("fnstcw %0" : "=m" (*&Old_Mask));
00302
00303 New_Mask = Old_Mask & UnMask;
00304
00305 __asm__ volatile("fldcw %0" : : "m" (*&New_Mask));
00306
00307 # if defined(__SSE__) || defined(__SSE2__)
00308
00309 # if defined(FLUSH_DENORM_TO_ZERO)
00310
00311
00312 SSE_Mask = 0x9900;
00313 # else
00314
00315 SSE_Mask = 0x1900;
00316 # endif
00317
00318
00319
00320 __asm__ volatile( "ldmxcsr %0" : : "m" (*&SSE_Mask) );
00321
00322 # endif
00323
00324
00325 # elif defined(__ia64)
00326
00327 # define FPSR_TRAP_VD (1 << 0)
00328 # define FPSR_TRAP_DD (1 << 1)
00329 # define FPSR_TRAP_ZD (1 << 2)
00330 # define FPSR_TRAP_OD (1 << 3)
00331 # define FPSR_TRAP_UD (1 << 4)
00332 # define FPSR_TRAP_ID (1 << 5)
00333
00334 # define FPSR_SF0_FTZ (1 << 6)
00335
00336 # if defined(__GNUC_EXCL__)
00337
00338 # define _IA64_REG_AR_FPSR 40
00339
00340 # define ia64_getreg( regnum ) __asm__ volatile( "mov %0=ar%1" : "=r" (fpsr) : "i"(regnum) )
00341 # define ia64_setreg( regnum, val ) __asm__ volatile( "mov ar%0=%1" :: "i" (regnum), "r"(val): "memory" )
00342 # define ia64_serialize __asm__ volatile( "srlz.i" );
00343
00344 volatile unsigned long fpsr, flags = FPSR_TRAP_VD | FPSR_TRAP_ZD | FPSR_TRAP_OD;
00345
00346 ia64_getreg( _IA64_REG_AR_FPSR );
00347 fpsr &= ~flags;
00348 # if defined(FLUSH_DENORM_TO_ZERO)
00349 fpsr |= FPSR_SF0_FTZ;
00350 # endif
00351 ia64_setreg( _IA64_REG_AR_FPSR, fpsr );
00352
00353 ia64_serialize;
00354
00355 # elif defined(__INTEL_COMPILER)
00356
00357 unsigned long fpsr = fpgetmask();
00358 fpsr |= FPSR_TRAP_VD | FPSR_TRAP_ZD | FPSR_TRAP_OD;
00359 fpsetmask( fpsr );
00360 # elif defined(__HP_aCC)
00361
00362 unsigned long fpsr = fegettrapenable();
00363 fpsr |= FPSR_TRAP_VD | FPSR_TRAP_ZD | FPSR_TRAP_OD;
00364 fesettrapenable( fpsr );
00365 # endif
00366
00367
00368 # elif defined(__sun) || defined(__sgi)
00369
00370 fp_except mask;
00371
00372
00373 # if defined(HAVE_SUNMATH) || defined(FLUSH_DENORM_TO_ZERO)
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410 nonstandard_arithmetic();
00411 # endif
00412
00413
00414 mask = fpgetmask();
00415 mask = mask | FP_X_INV | FP_X_OFL | FP_X_DZ;
00416 fpsetmask(mask);
00417
00418 # elif defined(__alpha) && defined(__linux) && defined(__GNUC__)
00419
00420
00421
00422
00423 # ifdef FE_NONIEEE_ENV
00424
00425
00426
00427 fesetenv(FE_NONIEEE_ENV);
00428 # endif
00429
00430 # endif
00431 return;
00432 }
00433
00434 void t_cpu::signal_handler(int sig)
00435 {
00436
00437 cpu.enable_traps();
00438 # ifdef _MSC_VER
00439
00440 signal( sig, &signal_handler );
00441 # endif
00442 throw bad_signal( sig );
00443 }
00444
00445
00446 void t_cpu::printDataPath() const
00447 {
00448 fprintf(ioQQQ, "The path is:\n");
00449 for( vector<string>::size_type i=1; i < cpu.chSearchPath.size()-1; ++i )
00450 fprintf( ioQQQ, " ==%s==\n", cpu.chSearchPath[i].c_str() );
00451 }
00452
00453
00454 void t_cpu::getPathList( const char* fname, vector<string>& PathList, access_scheme scheme ) const
00455 {
00456 DEBUG_ENTRY( "getPathList()" );
00457
00458 vector<string>::size_type begin, end;
00459
00460 switch( scheme )
00461 {
00462 case AS_DATA_ONLY:
00463 case AS_DATA_ONLY_TRY:
00464 case AS_DATA_OPTIONAL:
00465 begin = 1;
00466 end = cpu.chSearchPath.size()-1;
00467 break;
00468 case AS_DATA_LOCAL:
00469 case AS_DATA_LOCAL_TRY:
00470 begin = 1;
00471 end = cpu.chSearchPath.size();
00472 break;
00473 case AS_LOCAL_DATA:
00474 case AS_LOCAL_DATA_TRY:
00475 begin = 0;
00476 end = cpu.chSearchPath.size()-1;
00477 break;
00478 case AS_LOCAL_ONLY:
00479 case AS_LOCAL_ONLY_TRY:
00480 begin = 0;
00481 end = 1;
00482 break;
00483 default:
00484 TotalInsanity();
00485 }
00486
00487 PathList.clear();
00488 string FileName( fname );
00489 for( vector<string>::size_type i=begin; i < end; ++i )
00490 PathList.push_back( cpu.chSearchPath[i] + FileName );
00491 }
00492
00493 STATIC NORETURN void AbortErrorMessage( const char* fname, vector<string>& PathList, access_scheme scheme )
00494 {
00495 DEBUG_ENTRY( "AbortErrorMessage()" );
00496
00497 if( scheme == AS_DATA_OPTIONAL )
00498
00499 fprintf( ioQQQ, "\nI could not open the data file %s\n\n", fname );
00500 else
00501 fprintf( ioQQQ, "\nPROBLEM DISASTER I could not open the data file %s\n\n", fname );
00502 if( cpu.firstOpen() || scheme == AS_DATA_ONLY )
00503 {
00504
00505
00506 fprintf( ioQQQ, "Although there may be other reasons you have received this error,\n");
00507 fprintf( ioQQQ, "the most likely are that the path has not been properly set\n");
00508 fprintf( ioQQQ, "or that the path points to an old version of the data.\n\n");
00509 fprintf( ioQQQ, "Please have a look at the file path.h in the source directory\n");
00510 fprintf( ioQQQ, "to check how the variable CLOUDY_DATA_PATH is set - \n");
00511 fprintf( ioQQQ, "it should give the location of the data files I need.\n");
00512 fprintf( ioQQQ, "These are the files in the data download from the web site.\n\n");
00513 fprintf( ioQQQ, "Recompile the code with the correct data path set in path.h\n");
00514 fprintf( ioQQQ, "or use the shell command \nexport CLOUDY_DATA_PATH=\"/path/to/data\"\n to set the\n");
00515 fprintf( ioQQQ, "path from a bash command prompt.\n\n");
00516 cpu.printDataPath();
00517 }
00518 else
00519 {
00520
00521
00522
00523 fprintf( ioQQQ, "These are all the paths I tried:\n" );
00524 for( vector<string>::const_iterator ptr=PathList.begin(); ptr != PathList.end(); ++ptr )
00525 fprintf( ioQQQ, " ==%s==\n", ptr->c_str() );
00526
00527 if( scheme != AS_DATA_OPTIONAL )
00528 {
00529 fprintf( ioQQQ, "\nAlthough there may be other reasons you have received this error,\n");
00530 fprintf( ioQQQ, "the most likely are that you mistyped the file name, or that you\n");
00531 fprintf( ioQQQ, "are running Cloudy in the wrong directory. If you are running a\n");
00532 fprintf( ioQQQ, "COMPILE command, this needs to be done in the data directory.\n\n");
00533 fprintf( ioQQQ, "Otherwise, please have a look at the file path.h in the source\n");
00534 fprintf( ioQQQ, "directory to check how the variable CLOUDY_DATA_PATH is set - \n");
00535 fprintf( ioQQQ, "it should give the location of the data files I need.\n");
00536 fprintf( ioQQQ, "These are the files in the data download from the web site.\n\n");
00537 fprintf( ioQQQ, "Recompile the code with the correct data path set in path.h\n");
00538 fprintf( ioQQQ, "or use the shell command \nexport CLOUDY_DATA_PATH=\"/path/to/data\"\n to set the\n");
00539 fprintf( ioQQQ, "path from a bash command prompt.\n\n");
00540 }
00541 }
00542 fprintf(ioQQQ, "Sorry.\n\n\n");
00543 cdEXIT(EXIT_FAILURE);
00544 }
00545
00546 FILE* open_data( const char* fname, const char* mode, access_scheme scheme )
00547 {
00548 DEBUG_ENTRY( "open_data()" );
00549
00550 bool lgAbort = ( scheme == AS_DATA_ONLY || scheme == AS_DATA_OPTIONAL || scheme == AS_DATA_LOCAL ||
00551 scheme == AS_LOCAL_DATA || scheme == AS_LOCAL_ONLY );
00552
00553 vector<string> PathList;
00554 cpu.getPathList( fname, PathList, scheme );
00555
00556 FILE* handle = NULL;
00557 vector<string>::const_iterator ptr;
00558 for( ptr=PathList.begin(); ptr != PathList.end() && handle == NULL; ++ptr )
00559 {
00560 handle = fopen( ptr->c_str(), mode );
00561 if( trace.lgTrace )
00562 fprintf( ioQQQ, " open_data trying %s mode %s handle %p\n", ptr->c_str(), mode, handle );
00563 }
00564
00565 if( handle == NULL && lgAbort )
00566 AbortErrorMessage( fname, PathList, scheme );
00567
00568 ++cpu.nFileDone;
00569
00570 return handle;
00571 }
00572
00573 void open_data( fstream& stream, const char* fname, ios_base::openmode mode, access_scheme scheme )
00574 {
00575 DEBUG_ENTRY( "open_data()" );
00576
00577 bool lgAbort = ( scheme == AS_DATA_ONLY || scheme == AS_DATA_OPTIONAL || scheme == AS_DATA_LOCAL ||
00578 scheme == AS_LOCAL_DATA || scheme == AS_LOCAL_ONLY );
00579
00580 vector<string> PathList;
00581 cpu.getPathList( fname, PathList, scheme );
00582
00583 ASSERT( !stream.is_open() );
00584 vector<string>::const_iterator ptr;
00585 for( ptr=PathList.begin(); ptr != PathList.end() && !stream.is_open(); ++ptr )
00586 {
00587 stream.open( ptr->c_str(), mode );
00588 if( trace.lgTrace )
00589 fprintf( ioQQQ, " open_data trying %s succes? %c\n", ptr->c_str(), TorF(stream.is_open()) );
00590 }
00591
00592 if( !stream.is_open() && lgAbort )
00593 AbortErrorMessage( fname, PathList, scheme );
00594
00595 ++cpu.nFileDone;
00596 }
00597
00603 void set_NaN(sys_float &x)
00604 {
00605 if( sizeof(sys_float) == 4 )
00606 *reinterpret_cast<int32*>(&x) = cpu.Float_SNaN_Value;
00607 else
00608 x = -FLT_MAX;
00609 }
00610
00611 void set_NaN(sys_float x[],
00612 long n)
00613 {
00614 long i;
00615
00616 if( sizeof(sys_float) == 4 )
00617 {
00618 int32 *y = reinterpret_cast<int32*>(x);
00619 for( i=0; i < n; i++ )
00620 *y++ = cpu.Float_SNaN_Value;
00621 }
00622 else
00623 {
00624 for( i=0; i < n; i++ )
00625 x[i] = -FLT_MAX;
00626 }
00627 }
00628
00629 void set_NaN(double &x)
00630 {
00631 if( sizeof(double) == 8 )
00632 {
00633 # ifdef HAVE_INT64
00634 *reinterpret_cast<int64*>(&x) = cpu.Double_SNaN_Value;
00635 # else
00636 int32 *y = reinterpret_cast<int32*>(&x);
00637 *y++ = cpu.Double_SNaN_Value[0];
00638 *y = cpu.Double_SNaN_Value[1];
00639 # endif
00640 }
00641 else
00642 x = -DBL_MAX;
00643 }
00644
00645
00646 void set_NaN(double x[],
00647 long n)
00648 {
00649 long i;
00650
00651 if( sizeof(double) == 8 )
00652 {
00653 # ifdef HAVE_INT64
00654 int64 *y = reinterpret_cast<int64*>(x);
00655 for( i=0; i < n; i++ )
00656 *y++ = cpu.Double_SNaN_Value;
00657 # else
00658 int32 *y = reinterpret_cast<int32*>(x);
00659 for( i=0; i < n; i++ )
00660 {
00661 *y++ = cpu.Double_SNaN_Value[0];
00662 *y++ = cpu.Double_SNaN_Value[1];
00663 }
00664 # endif
00665 }
00666 else
00667 {
00668 for( i=0; i < n; i++ )
00669 x[i] = -DBL_MAX;
00670 }
00671 }
00672
00674 bool MyIsnan(const sys_float &x)
00675 {
00676 if( sizeof(sys_float) == 4 && FLT_MAX_EXP-FLT_MIN_EXP+3 == 256 )
00677 {
00678 const int32 *p = reinterpret_cast<const int32*>(&x);
00679 int32 r = *p & 0x7f800000; r ^= 0x7f800000;
00680 int32 s = *p & 0x007fffff;
00681 return ( r == 0 && s != 0 );
00682 }
00683 else
00684
00685 return false;
00686 }
00687
00689 bool MyIsnan(const double &x)
00690 {
00691 if( sizeof(double) == 8 && DBL_MAX_EXP-DBL_MIN_EXP+3 == 2048 )
00692 {
00693 # ifdef HAVE_INT64
00694 const int64 *p = reinterpret_cast<const int64*>(&x);
00695 int64 r = *p & 0x7ff0000000000000; r ^= 0x7ff0000000000000;
00696 int64 s = *p & 0x000fffffffffffff;
00697 return ( r == 0 && s != 0 );
00698 # else
00699 const int32 *p = reinterpret_cast<const int32*>(&x);
00700 if( cpu.little_endian() )
00701 {
00702 int32 r = p[1] & 0x7ff00000; r ^= 0x7ff00000;
00703 int32 s = p[1] & 0x000fffff; s |= p[0];
00704 return ( r == 0 && s != 0 );
00705 }
00706 else if( cpu.big_endian() )
00707 {
00708 int32 r = p[0] & 0x7ff00000; r ^= 0x7ff00000;
00709 int32 s = p[0] & 0x000fffff; s |= p[1];
00710 return ( r == 0 && s != 0 );
00711 }
00712 else
00713
00714 return false;
00715 # endif
00716 }
00717 else
00718
00719 return false;
00720 }