[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: netCDF question (maybe it's actually a C question)



> 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