/home66/gary/public_html/cloudy/c08_branch/source/cpu.cpp

Go to the documentation of this file.
00001 /* This file is part of Cloudy and is copyright (C)1978-2008 by Gary J. Ferland and
00002  * others.  For conditions of distribution and use see copyright notice in license.txt */
00004 #if defined(__HP_aCC)
00005 /* this is for the HP compiler on the sdx */
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 /* the redefinition of float in cddefines.h can cause problems in system headers
00032  * hence these includes MUST come after the system header includes above */
00033 #include "cddefines.h"
00034 #include "path.h"
00035 #include "trace.h"
00036 
00037 /* NB NB - this constructor needs to be called before any of the user code is executed !! */
00038 t_cpu::t_cpu()
00039 {
00040         DEBUG_ENTRY( "t_cpu()" );
00041 
00042 #ifdef CATCH_SIGNAL
00043         // set up signal handlers so that we can properly terminate MPI runs...
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                 // is the signal valid?
00057                 if( sigaction( sig, NULL, NULL ) == 0 )
00058                         // these two are for suspending and resuming a job
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         /* >>chng 05 dec 14, add test of endianness of the CPU, PvH */
00075         endian.c[0] = 0x12;
00076         endian.c[1] = 0x34;
00077         endian.c[2] = 0x56;
00078         endian.c[3] = 0x78;
00079 
00080         /* >>chng 05 dec 15, add signaling NaN for float and double to cpu struct, PvH */
00081         /* in C++ this should be replaced by numeric_limits<TYPE>::signaling_NaN() */
00082         if( sizeof(sys_float) == 4 )
00083         {
00084 #               ifdef __mips
00085                 /* definition of signaling and quiet NaN is reversed on MIPS */
00086                 Float_SNaN_Value = 0xffffffff;
00087 #               else
00088                 if( big_endian() || little_endian() )
00089                 {
00090                         /* this should work on most modern CPU's */
00091                         Float_SNaN_Value = 0xffbfffff;
00092                 }
00093                 else
00094                 {
00095                         /* this is an unusual CPU -> bit pattern for SNaN is unknown */
00096                         Float_SNaN_Value = -1;
00097                 }
00098 #               endif
00099         }
00100         else
00101         {
00102                 /* this is an unusual CPU -> bit pattern for SNaN is unknown */
00103                 Float_SNaN_Value = -1;
00104         }
00105 
00106 #       ifdef HAVE_INT64
00107 
00108         if( sizeof(double) == 8 )
00109         {
00110 #               ifdef __mips
00111                 /* definition of signaling and quiet NaN is reversed on MIPS */
00112                 Double_SNaN_Value = 0xffffffffffffffff;
00113 #               else
00114                 /* this should work on most modern CPU's */
00115                 Double_SNaN_Value = 0xfff7ffffffbfffff;
00116 #               endif
00117         }
00118         else
00119         {
00120                 /* this is an unusual CPU -> bit pattern for SNaN is unknown */
00121                 Double_SNaN_Value = -1;
00122         }
00123 
00124 #       else
00125 
00126         if( sizeof(double) == 8 )
00127         {
00128 #               ifdef __mips
00129                 /* definition of signaling and quiet NaN is reversed on MIPS */
00130                 Double_SNaN_Value[0] = 0xffffffff;
00131                 Double_SNaN_Value[1] = 0xffffffff;
00132 #               else
00133                 if( big_endian() )
00134                 {
00135                         /* this should work on most modern CPU's */
00136                         Double_SNaN_Value[0] = 0xfff7ffff;
00137                         Double_SNaN_Value[1] = 0xffbfffff;
00138                 }
00139                 else if( little_endian() )
00140                 {
00141                         /* this should work on most modern CPU's */
00142                         Double_SNaN_Value[0] = 0xffbfffff;
00143                         Double_SNaN_Value[1] = 0xfff7ffff;
00144                 }
00145                 else
00146                 {
00147                         /* this is an unusual CPU -> bit pattern for SNaN is unknown */
00148                         Double_SNaN_Value[0] = -1;
00149                         Double_SNaN_Value[1] = -1;
00150                 }
00151 #               endif
00152         }
00153         else
00154         {
00155                 /* this is an unusual CPU -> bit pattern for SNaN is unknown */
00156                 Double_SNaN_Value[0] = -1;
00157                 Double_SNaN_Value[1] = -1;
00158         }
00159 
00160 #       endif
00161 
00162         /* set FP environment to trap FP exceptions */
00163         enable_traps();
00164 
00165         /* default is for failed asserts not to abort */
00166         p_lgAssertAbort = false;
00167 
00168         const char *str;
00169 
00170         /* determine the no. of CPUs on this machine; used by PHYMIR, grid command, .... */
00171 #       if defined(_SC_NPROCESSORS_ONLN)  /* Linux, Sun Sparc, DEC Alpha */
00172         n_avail_CPU = sysconf(_SC_NPROCESSORS_ONLN);
00173 #       elif defined(_SC_NPROC_ONLN)      /* SGI Iris */
00174         n_avail_CPU = sysconf(_SC_NPROC_ONLN);
00175 #       elif defined(_SC_CRAY_NCPU)       /* Cray */
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         /* Other systems, supply no. of CPUs on OPTIMIZE PHYMIR command line */
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         /* pick up the path from the environment, if set by user */
00207         const char *path = getenv( "CLOUDY_DATA_PATH" );
00208 
00209         /* if the environment variable was not set, the default set in path.h takes effect */
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( "" ); // the current working directory should be first and last
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                         /* get last valid char */
00229                         char chEnd = *chSearchPath[i].rbegin();
00230 
00231                         /* make sure path ends with directory separator */
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         /* >>chng 01 aug 07, added code to circumvent math library bug with g++ on
00243          * alpha-linux machines, see bug report 51072 on http://bugzilla.redhat.com, PvH */
00244         /* >>chng 01 apr 17, added code for Solaris and SGI operating systems, PvH */
00245         /* this routine contains no code for alphas or crays, they do not need
00246          * special code to enable FP exceptions since they are enabled by default */
00247 
00248         /* there is no command line option on MS Visual Studio to force crash */
00249 #       if defined(_MSC_VER)
00250         volatile unsigned int NewMask;
00251 
00252         /* | is a bitwise inclusive or, turns on bits
00253          * 0|0 = 0
00254          * 0|1 = 1|0 = 1|1 = 1 */
00255         NewMask = _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_INVALID;
00256         /* ~ is the unary bitwise complement - all bits flip */ 
00257         NewMask = ~NewMask;
00258         _controlfp( NewMask , _MCW_EM );
00259 
00260         /* this is the code for Linux PC (but not Linux alpha) to force crash */
00261         /* >>chng 04 apr 26, added support for AMD64, enable FPE traps for SSE/SSE2, PvH */
00262         /* >>chng 06 aug 12, added support for Apple MacOSX, and hopefully also Solaris x86, PvH */
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  /* Invalid          */
00270 #       define _FPU_MASK_DM  0x02  /* Denormalized     */
00271 #       define _FPU_MASK_ZM  0x04  /* Division-by-zero */
00272 #       define _FPU_MASK_OM  0x08  /* Overflow         */
00273 #       define _FPU_MASK_UM  0x10  /* Underflow        */
00274 #       define _FPU_MASK_PM  0x20  /* Inexact          */
00275 
00276         /*  | is a bitwise inclusive or, turns on bits     */
00277         /* 0|0 = 0                                         */
00278         /* 0|1 = 1|0 = 1|1 = 1                             */
00279 
00280         /*  ~ is the unary bitwise complement - all bits flip */
00281 
00282         /* this enables FPE traps for regular i387 FP instructions */
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         /* using this causes denormalized numbers to be flushed to zero,
00296          * which will speed up the code on Pentium 4 processors */
00297         SSE_Mask = 0x9900;
00298 #       else
00299         /* this version allows denormalized numbers to be retained */
00300         SSE_Mask = 0x1900;
00301 #       endif
00302 
00303         /* this enables FPE traps for SSE/SSE2 instructions */
00304 
00305         __asm__ volatile( "ldmxcsr %0" : : "m" (*&SSE_Mask) );
00306 
00307 #       endif
00308 
00309         /* this is for IA64 systems running g++ or icc (e.g. SGI, HP, ...) */
00310 #       elif defined(__ia64)
00311 
00312 #       define FPSR_TRAP_VD     (1 << 0)        /* invalid op trap disabled */
00313 #       define FPSR_TRAP_DD     (1 << 1)        /* denormal trap disabled */
00314 #       define FPSR_TRAP_ZD     (1 << 2)        /* zero-divide trap disabled */
00315 #       define FPSR_TRAP_OD     (1 << 3)        /* overflow trap disabled */
00316 #       define FPSR_TRAP_UD     (1 << 4)        /* underflow trap disabled */
00317 #       define FPSR_TRAP_ID     (1 << 5)        /* inexact trap disabled */
00318 
00319 #       define FPSR_SF0_FTZ     (1 << 6)        /* flush denormalized numbers to zero */
00320 
00321 #       if defined(__GNUC_EXCL__)
00322         /* __asm__ instructions are not supported by icc as of v9.0 */
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         /* this prevents RAW and WAW dependency violations in case this ever gets inlined... */
00338         ia64_serialize;
00339 
00340 #       elif defined(__INTEL_COMPILER)
00341         /* this is for icc on IA64 SGI machines */
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         /* this is for the HP compiler on the sdx */
00347         unsigned long fpsr = fegettrapenable(); 
00348         fpsr |= FPSR_TRAP_VD | FPSR_TRAP_ZD | FPSR_TRAP_OD;
00349         fesettrapenable( fpsr ); 
00350 #       endif /* defined(__GNUC_EXCL__) */
00351 
00352         /* this is for Solaris and SGI to force crash */
00353 #       elif defined(__sun) || defined(__sgi)
00354 
00355         fp_except mask;
00356 
00357         /* >>chng 05 dec 30, accept FLUSH_DENORM_TO_ZERO as a synonym for HAVE_SUNMATH, PvH */
00358 #       if defined(HAVE_SUNMATH) || defined(FLUSH_DENORM_TO_ZERO)
00359 
00360         /* >>chng 01 oct 09, disable gradual underflow on ultrasparc whith g++
00361          * (only needed for versions < 3.1 or >= 4.3.0, see Note 1).
00362          *
00363          * compile this module with:
00364          *     g++ [ other options... ] -I<include-dir> -DHAVE_SUNMATH -c cpu.cpp
00365          * link the program with:
00366          *     g++ -L<library-dir> -o cloudy.exe *.o -lsunmath
00367          *
00368          * you probably need to use -I<include-dir> and -L<library-dir> to point the
00369          * compiler/linker to the location of the sunmath.h header file and libsunmath.so
00370          * library (e.g., -I/opt/SUNWspro/prod/include/cc -L/opt/SUNWspro/lib; note that
00371          * the actual location may vary from one installation to another).
00372          * See also bug report 4487 on http://gcc.gnu.org/bugzilla/
00373          *
00374          * Note 1: Starting with g++ 3.1, bug 4487 has been solved: -funsafe-math-optimizations
00375          * will automatically disable gradual underflow. Hence using nonstandard_arithmetic()
00376          * is no longer necessary. The option -funsafe-math-optimizations should be included
00377          * both when compiling and linking:
00378          *
00379          * g++ [ other options... ] -funsafe-math-optimizations -c *.c
00380          * g++ [ other options... ] -funsafe-math-optimizations -o cloudy.exe *.o
00381          *
00382          * Starting with g++ 4.3.0 the -funsafe-math-optimizations option can no longer be
00383          * used as it implicitly enables -fno-trapping-math, which is unsafe for Cloudy
00384          * because we do trap floating point exceptions.
00385          *
00386          * Note 2: Don't use nonstandard_arithmetic() with CC (the SunWorks/Forte compiler);
00387          * use the -fast commandline option instead to disable gradual underflow (or use
00388          * -fnonstd if you don't want all the other options enabled by -fast). The option
00389          * -fast (or -fnonstd) should be included both when compiling and linking:
00390          *
00391          * CC [ other options... ] -fast -c *.c
00392          * CC -fast -o cloudy.exe *.o
00393          *
00394          * PvH */
00395         nonstandard_arithmetic();
00396 #       endif
00397 
00398         /* enable floating point exceptions on sun and sgi */
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         /* the following is not supported on all hardware platforms, but certainly for EV56
00406          * and later. earlier versions may work as well, but that has not been tested.
00407          * for details see https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=51072 */
00408 #       ifdef FE_NONIEEE_ENV
00409         /* this prevents the infamous math library bug when compiling with gcc on alpha-linux
00410          * machines. if this doesn't work on your system, the only alternative is to link
00411          * against the Compaq math library: gcc *.o -lcpml -lm, or use ccc itself, PvH */
00412         fesetenv(FE_NONIEEE_ENV);
00413 #       endif
00414 
00415 #       endif
00416         return;
00417 }
00418 
00419 void t_cpu::signal_handler(int sig)
00420 {
00421         // when an FPE is caught, the mask is reset...
00422         cpu.enable_traps();
00423 #       ifdef _MSC_VER
00424         // at this point the signal handler has reverted to the default handler
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                         // presence is optional -> make warning less scary...
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                         // failed on very first open -> most likely path is not correct
00495                         // failed on AS_DATA_ONLY -> CLOUDY_DATA_PATH may point to obsolete data dir
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                         // failed on search including local directory -> most likely the file name
00511                         // was mistyped on a compile command, or Cloudy is run in the wrong directory
00512                         // if scheme == AS_DATA_OPTIONAL, this most likely is a stellar grid that is not installed.
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                         // AS_DATA_OPTIONAL files should provide their own message (currently only stellar grids)
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[], /* x[n] */
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 /* set_NaN - set NaN */
00594 void set_NaN(double x[], /* x[n] */
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                 /* we don't understand this CPU */
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                         /* we don't understand this CPU */
00662                         return false;
00663 #               endif
00664         }
00665         else
00666                 /* we don't understand this CPU */
00667                 return false;
00668 }

Generated on Mon Feb 16 12:01:14 2009 for cloudy by  doxygen 1.4.7