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