This archive contains answers to questions sent to Unidata support through mid-2025. Note that the archive is no longer being updated. We provide the archive for reference; many of the answers presented here remain technically correct, even if somewhat outdated. For the most up-to-date information on the use of NSF Unidata software and data services, please consult the Software Documentation first.
> From: Brian Eaton <address@hidden> > To: address@hidden <address@hidden> > Date: Thursday, March 26, 1998 3:49 PM > Subject: netcdf question > > > Hi John, > > I have a netCDF question for you (well, maybe it's actually a C question). > I'm in the process of updating ccm2nc so that it will write NC_DOUBLE to > the output file if requested. To support this I need to use double instead > of float as the internal data representation on ieee machines. I have a > type called Hfloat which is typedef'd to float on the cray and double on > and ieee machine. Here is an example of the code that I'm using to output > a single value: > > Hfloat val = 1.e5; > #ifdef CRAY > handleError( nc_put_var_float( ncid, p0_id, &val ) ); > #else > handleError( nc_put_var_double( ncid, p0_id, &val ) ); > #endif > > This is kind of clumsy, especially when I have to make hundreds of calls > like this. I've thought about using a pointer to a function, but I don't > think I can do it because the function prototypes need to match between the > actual function and the pointer, but nc_put_var_float and nc_put_var_double > have different prototypes. > > Do you know an elegant way to do this? > > Thanks, > Brian Brian: Presumably someplace (like an include file) you have a code sequence like: #ifdef CRAY typedef float Hfloat; #else #typedef double Hfloat; #endif What I would do is define some macros that call the netcdf functions according to the new type. I'd do this at the same place as I declare the new type. Also, you probably want to decouple the 'CRAY' definition from the decision about which floating point to use from the machine type (I'll explain more about this later). #if SIZEOF_FLOAT == 8 #define USE_DOUBLE_AS_FLOAT #endif #if USE_DOUBLE_AS_FLOAT typedef double Hfloat; #define nc_put_var_Hfloat(ncid, varid, valp) \ nc_put_var_double((ncid), (varid), (valp)) /* ... other definitions as needed */ #else typedef float Hfloat; #define nc_put_var_Hfloat(ncid, varid, valp) \ nc_put_var_float((ncid), (varid), (valp)) /* ... same other definitions, using nc_xxx_float() */ #endif Then, whenever you use and Hfloat, use the appropriate nc_xxx_Hfloat() 'function'. Hfloat val = 1.e5; handleError( nc_put_var_Hfloat( ncid, p0_id, &val ) ); If you like, you could actually define these as inline functions rather than macros, or use the CRI mechanism which gives multiple names to the same extern symbol. (I forget what this last thing is called.) It is probably a good idea to use some other macro than 'CRAY' to decide whether you want to use 'double' or 'float'. There are compilation environments which #define CRAY but where the 'float' is 32 bits (t3d). I think there may be compiler flags on other CRAY's that set the double to be 64 bits even when the float is 64, and so on. Also, you might run into the same problem on another machine, like and NEC SX-4, which doesn't #define CRAY. -glenn