question about float to int type conversion...

Howdy HDFers!

I sent this question to Quincey last week, but he hasn't
replied. Perhaps someone left his office door unlocked and he wandered
off. ;-)

I'm writing some floats to ints, and the floats are all smaller or
larger than a 4 byte signed int allows, so I expect them all to
overflow. However, they don't.

The output below shows the problem. Isn't it true that when I try to
write these floats to an int, I should get an overflow each time?

   float float_data_out2[DIM1_LEN] = {(float)INT_MIN - 1.0, (float)INT_MIN - 
1.0, (float)INT_MAX + 129.0};

That is, writing the above array should call my exception function
three times, but it is only called once, for the last value (and if
that is +128, it's not called for that either).

I don't understand this behavior. I am getting INT_MIN from limits.h:
/* Minimum and maximum values a `signed int' can hold.  */
#  define INT_MIN       (-INT_MAX - 1)
#  define INT_MAX       2147483647

So why doesn't it generate an overflow?

Thanks!

Ed

output:

*** Checking HDF5 data type conversions.
*** creating test file...ok.
*** reading int dataset as floats...ok.
*** reading float dataset as uchars...ok.
*** writing out of range floats to int dataset...
float_data_out2[0]=-2147483648.000000
(int)float_data_out2[0]=-2147483648
float_data_out2[1]=-2147483648.000000
(int)float_data_out2[1]=-2147483648
float_data_out2[2]=2147483904.000000
(int)float_data_out2[2]=-2147483648
overflow_count=1
unexpected result, tst_h_converts.c, line: 546
1 failures
1 errors detected! Sorry!

tst_h_converts.c:

/* This is part of the netCDF package.
   Copyright 2005 University Corporation for Atmospheric Research/Unidata
   See COPYRIGHT file for conditions of use.

   Test HDF5 file code. These are not intended to be exhaustive tests,
   but they use HDF5 the same way that netCDF-4 does, so if these
   tests don't work, than netCDF-4 won't work either.

   $Id: tst_h_converts.c,v 1.2 2005/06/23 01:07:12 ed Exp $
*/
#include "tests.h"
#include <limits.h>

#define FILE_NAME "tst_h_converts.h5"
#define GRP_NAME "my_group"
#define INT_VAR_NAME "int_var"
#define FLOAT_VAR_NAME "float_var"
#define SCHAR_VAR_NAME "schar_var"
#define DIM1_LEN 3

/* This function is called when there is an overflow in a read/write
 * operation. Pass the fill value in as user_data. */
H5T_conv_ret_t
except_func(int except_type, hid_t src_id, hid_t dst_id, 
            void *src_buf, void *dst_buf, void *user_data)
{
   /*printf("except_func: except_type %d\n", except_type);*/

   if(except_type == H5T_CONV_EXCEPT_RANGE_HI ||
      except_type == H5T_CONV_EXCEPT_RANGE_LOW)
   {
      if (H5Tequal(dst_id, H5T_STD_I8BE) > 0 ||
          H5Tequal(dst_id, H5T_STD_I8LE) > 0)
      {
         if (H5Tequal(src_id, H5T_STD_I8BE) > 0 ||
             H5Tequal(src_id, H5T_STD_I8LE) > 0)
            *(signed char *)dst_buf = *(signed char *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U8BE) ||
                  H5Tequal(src_id, H5T_STD_U8LE) > 0)
            *(signed char *)dst_buf = (unsigned char)*(float *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I16BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I16LE) > 0)
            *(signed char *)dst_buf = *(signed short *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U16BE) ||
                  H5Tequal(src_id, H5T_STD_U16LE) > 0)
            *(signed char *)dst_buf = *(unsigned short *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I32BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I32LE) > 0)
            *(signed char *)dst_buf = *(signed int *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U32BE) ||
                  H5Tequal(src_id, H5T_STD_U32LE) > 0)
            *(signed char *)dst_buf = *(unsigned int *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I64BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I64LE) > 0)
            *(signed char *)dst_buf = *(signed long long *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U64BE) ||
                  H5Tequal(src_id, H5T_STD_U64LE) > 0)
            *(signed char *)dst_buf = *(unsigned long long *)src_buf;
         else if (H5Tequal(src_id, H5T_IEEE_F32BE) > 0 ||
                  H5Tequal(src_id, H5T_IEEE_F32LE) > 0)
            *(signed char *)dst_buf = *(float *)src_buf;
         else if (H5Tequal(src_id, H5T_IEEE_F64BE) ||
                  H5Tequal(src_id, H5T_IEEE_F64LE) > 0)
            *(signed char *)dst_buf = *(double *)src_buf;
         else
         {
            printf("Unknown type!\n");
            return H5T_CONV_UNHANDLED;
         }       
      }
      else if (H5Tequal(dst_id, H5T_STD_U8BE) ||
               H5Tequal(dst_id, H5T_STD_U8LE) > 0)
      {
         if (H5Tequal(src_id, H5T_STD_I8BE) > 0 ||
             H5Tequal(src_id, H5T_STD_I8LE) > 0)
            *(unsigned char *)dst_buf = *(signed char *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U8BE) ||
                  H5Tequal(src_id, H5T_STD_U8LE) > 0)
            *(unsigned char *)dst_buf = (unsigned char)*(float *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I16BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I16LE) > 0)
            *(unsigned char *)dst_buf = *(signed short *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U16BE) ||
                  H5Tequal(src_id, H5T_STD_U16LE) > 0)
            *(unsigned char *)dst_buf = *(unsigned short *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I32BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I32LE) > 0)
            *(unsigned char *)dst_buf = *(signed int *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U32BE) ||
                  H5Tequal(src_id, H5T_STD_U32LE) > 0)
            *(unsigned char *)dst_buf = *(unsigned int *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I64BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I64LE) > 0)
            *(unsigned char *)dst_buf = *(signed long long *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U64BE) ||
                  H5Tequal(src_id, H5T_STD_U64LE) > 0)
            *(unsigned char *)dst_buf = *(unsigned long long *)src_buf;
         else if (H5Tequal(src_id, H5T_IEEE_F32BE) > 0 ||
                  H5Tequal(src_id, H5T_IEEE_F32LE) > 0)
            *(unsigned char *)dst_buf = *(float *)src_buf;
         else if (H5Tequal(src_id, H5T_IEEE_F64BE) ||
                  H5Tequal(src_id, H5T_IEEE_F64LE) > 0)
            *(unsigned char *)dst_buf = *(double *)src_buf;
         else
         {
            printf("Unknown type!\n");
            return H5T_CONV_UNHANDLED;
         }       
      }
      else if (H5Tequal(dst_id, H5T_STD_I16BE) > 0 ||
               H5Tequal(dst_id, H5T_STD_I16LE) > 0)
      {
         if (H5Tequal(src_id, H5T_STD_I8BE) > 0 ||
             H5Tequal(src_id, H5T_STD_I8LE) > 0)
            *(short *)dst_buf = *(signed char *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U8BE) ||
                  H5Tequal(src_id, H5T_STD_U8LE) > 0)
            *(short *)dst_buf = (unsigned char)*(float *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I16BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I16LE) > 0)
            *(short *)dst_buf = *(signed short *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U16BE) ||
                  H5Tequal(src_id, H5T_STD_U16LE) > 0)
            *(short *)dst_buf = *(unsigned short *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I32BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I32LE) > 0)
            *(short *)dst_buf = *(signed int *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U32BE) ||
                  H5Tequal(src_id, H5T_STD_U32LE) > 0)
            *(short *)dst_buf = *(unsigned int *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I64BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I64LE) > 0)
            *(short *)dst_buf = *(signed long long *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U64BE) ||
                  H5Tequal(src_id, H5T_STD_U64LE) > 0)
            *(short *)dst_buf = *(unsigned long long *)src_buf;
         else if (H5Tequal(src_id, H5T_IEEE_F32BE) > 0 ||
                  H5Tequal(src_id, H5T_IEEE_F32LE) > 0)
            *(short *)dst_buf = *(float *)src_buf;
         else if (H5Tequal(src_id, H5T_IEEE_F64BE) ||
                  H5Tequal(src_id, H5T_IEEE_F64LE) > 0)
            *(short *)dst_buf = *(double *)src_buf;
         else
         {
            printf("Unknown type!\n");
            return H5T_CONV_UNHANDLED;
         }       
      }
      else if (H5Tequal(dst_id, H5T_STD_U16BE) ||
               H5Tequal(dst_id, H5T_STD_U16LE) > 0)
      {
         if (H5Tequal(src_id, H5T_STD_I8BE) > 0 ||
             H5Tequal(src_id, H5T_STD_I8LE) > 0)
            *(unsigned short *)dst_buf = *(signed char *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U8BE) ||
                  H5Tequal(src_id, H5T_STD_U8LE) > 0)
            *(unsigned short *)dst_buf = (unsigned char)*(float *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I16BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I16LE) > 0)
            *(unsigned short *)dst_buf = *(signed short *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U16BE) ||
                  H5Tequal(src_id, H5T_STD_U16LE) > 0)
            *(unsigned short *)dst_buf = *(unsigned short *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I32BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I32LE) > 0)
            *(unsigned short *)dst_buf = *(signed int *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U32BE) ||
                  H5Tequal(src_id, H5T_STD_U32LE) > 0)
            *(unsigned short *)dst_buf = *(unsigned int *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I64BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I64LE) > 0)
            *(unsigned short *)dst_buf = *(signed long long *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U64BE) ||
                  H5Tequal(src_id, H5T_STD_U64LE) > 0)
            *(unsigned short *)dst_buf = *(unsigned long long *)src_buf;
         else if (H5Tequal(src_id, H5T_IEEE_F32BE) > 0 ||
                  H5Tequal(src_id, H5T_IEEE_F32LE) > 0)
            *(unsigned short *)dst_buf = *(float *)src_buf;
         else if (H5Tequal(src_id, H5T_IEEE_F64BE) ||
                  H5Tequal(src_id, H5T_IEEE_F64LE) > 0)
            *(unsigned short *)dst_buf = *(double *)src_buf;
         else
         {
            printf("Unknown type!\n");
            return H5T_CONV_UNHANDLED;
         }       
      }
      else if (H5Tequal(dst_id, H5T_STD_I32BE) > 0 ||
               H5Tequal(dst_id, H5T_STD_I32LE) > 0)
      {
         if (H5Tequal(src_id, H5T_STD_I8BE) > 0 ||
             H5Tequal(src_id, H5T_STD_I8LE) > 0)
            *(int *)dst_buf = *(signed char *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U8BE) ||
                  H5Tequal(src_id, H5T_STD_U8LE) > 0)
            *(int *)dst_buf = (unsigned char)*(float *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I16BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I16LE) > 0)
            *(int *)dst_buf = *(signed short *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U16BE) ||
                  H5Tequal(src_id, H5T_STD_U16LE) > 0)
            *(int *)dst_buf = *(unsigned short *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I32BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I32LE) > 0)
            *(int *)dst_buf = *(signed int *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U32BE) ||
                  H5Tequal(src_id, H5T_STD_U32LE) > 0)
            *(int *)dst_buf = *(unsigned int *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I64BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I64LE) > 0)
            *(int *)dst_buf = *(signed long long *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U64BE) ||
                  H5Tequal(src_id, H5T_STD_U64LE) > 0)
            *(int *)dst_buf = *(unsigned long long *)src_buf;
         else if (H5Tequal(src_id, H5T_IEEE_F32BE) > 0 ||
                  H5Tequal(src_id, H5T_IEEE_F32LE) > 0)
            *(int *)dst_buf = *(float *)src_buf;
         else if (H5Tequal(src_id, H5T_IEEE_F64BE) ||
                  H5Tequal(src_id, H5T_IEEE_F64LE) > 0)
            *(int *)dst_buf = *(double *)src_buf;
         else
         {
            printf("Unknown type!\n");
            return H5T_CONV_UNHANDLED;
         }       
      }
      else if (H5Tequal(dst_id, H5T_STD_U32BE) ||
               H5Tequal(dst_id, H5T_STD_U32LE) > 0)
      {
         if (H5Tequal(src_id, H5T_STD_I8BE) > 0 ||
             H5Tequal(src_id, H5T_STD_I8LE) > 0)
            *(unsigned int *)dst_buf = *(signed char *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U8BE) ||
                  H5Tequal(src_id, H5T_STD_U8LE) > 0)
            *(unsigned int *)dst_buf = (unsigned char)*(float *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I16BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I16LE) > 0)
            *(unsigned int *)dst_buf = *(signed short *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U16BE) ||
                  H5Tequal(src_id, H5T_STD_U16LE) > 0)
            *(unsigned int *)dst_buf = *(unsigned short *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I32BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I32LE) > 0)
            *(unsigned int *)dst_buf = *(signed int *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U32BE) ||
                  H5Tequal(src_id, H5T_STD_U32LE) > 0)
            *(unsigned int *)dst_buf = *(unsigned int *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I64BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I64LE) > 0)
            *(unsigned int *)dst_buf = *(signed long long *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U64BE) ||
                  H5Tequal(src_id, H5T_STD_U64LE) > 0)
            *(unsigned int *)dst_buf = *(unsigned long long *)src_buf;
         else if (H5Tequal(src_id, H5T_IEEE_F32BE) > 0 ||
                  H5Tequal(src_id, H5T_IEEE_F32LE) > 0)
            *(unsigned int *)dst_buf = *(float *)src_buf;
         else if (H5Tequal(src_id, H5T_IEEE_F64BE) ||
                  H5Tequal(src_id, H5T_IEEE_F64LE) > 0)
            *(unsigned int *)dst_buf = *(double *)src_buf;
         else
         {
            printf("Unknown type!\n");
            return H5T_CONV_UNHANDLED;
         }       
      }
      else if (H5Tequal(dst_id, H5T_STD_I64BE) > 0 ||
               H5Tequal(dst_id, H5T_STD_I64LE) > 0)
      {
         if (H5Tequal(src_id, H5T_STD_I8BE) > 0 ||
             H5Tequal(src_id, H5T_STD_I8LE) > 0)
            *(signed long long *)dst_buf = *(signed char *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U8BE) ||
                  H5Tequal(src_id, H5T_STD_U8LE) > 0)
            *(signed long long *)dst_buf = (unsigned char)*(float *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I16BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I16LE) > 0)
            *(signed long long *)dst_buf = *(signed short *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U16BE) ||
                  H5Tequal(src_id, H5T_STD_U16LE) > 0)
            *(signed long long *)dst_buf = *(unsigned short *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I32BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I32LE) > 0)
            *(signed long long *)dst_buf = *(signed int *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U32BE) ||
                  H5Tequal(src_id, H5T_STD_U32LE) > 0)
            *(signed long long *)dst_buf = *(unsigned int *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I64BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I64LE) > 0)
            *(signed long long *)dst_buf = *(signed long long *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U64BE) ||
                  H5Tequal(src_id, H5T_STD_U64LE) > 0)
            *(signed long long *)dst_buf = *(unsigned long long *)src_buf;
         else if (H5Tequal(src_id, H5T_IEEE_F32BE) > 0 ||
                  H5Tequal(src_id, H5T_IEEE_F32LE) > 0)
            *(signed long long *)dst_buf = *(float *)src_buf;
         else if (H5Tequal(src_id, H5T_IEEE_F64BE) ||
                  H5Tequal(src_id, H5T_IEEE_F64LE) > 0)
            *(signed long long *)dst_buf = *(double *)src_buf;
         else
         {
            printf("Unknown type!\n");
            return H5T_CONV_UNHANDLED;
         }       
      }
      else if (H5Tequal(dst_id, H5T_STD_U64BE) ||
               H5Tequal(dst_id, H5T_STD_U64LE) > 0)
      {
         if (H5Tequal(src_id, H5T_STD_I8BE) > 0 ||
             H5Tequal(src_id, H5T_STD_I8LE) > 0)
            *(unsigned long long *)dst_buf = *(signed char *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U8BE) ||
                  H5Tequal(src_id, H5T_STD_U8LE) > 0)
            *(unsigned long long *)dst_buf = (unsigned char)*(float *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I16BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I16LE) > 0)
            *(unsigned long long *)dst_buf = *(signed short *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U16BE) ||
                  H5Tequal(src_id, H5T_STD_U16LE) > 0)
            *(unsigned long long *)dst_buf = *(unsigned short *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I32BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I32LE) > 0)
            *(unsigned long long *)dst_buf = *(signed int *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U32BE) ||
                  H5Tequal(src_id, H5T_STD_U32LE) > 0)
            *(unsigned long long *)dst_buf = *(unsigned int *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I64BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I64LE) > 0)
            *(unsigned long long *)dst_buf = *(signed long long *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U64BE) ||
                  H5Tequal(src_id, H5T_STD_U64LE) > 0)
            *(unsigned long long *)dst_buf = *(unsigned long long *)src_buf;
         else if (H5Tequal(src_id, H5T_IEEE_F32BE) > 0 ||
                  H5Tequal(src_id, H5T_IEEE_F32LE) > 0)
            *(unsigned long long *)dst_buf = *(float *)src_buf;
         else if (H5Tequal(src_id, H5T_IEEE_F64BE) ||
                  H5Tequal(src_id, H5T_IEEE_F64LE) > 0)
            *(unsigned long long *)dst_buf = *(double *)src_buf;
         else
         {
            printf("Unknown type!\n");
            return H5T_CONV_UNHANDLED;
         }       
      }
      else if (H5Tequal(dst_id, H5T_IEEE_F32BE) > 0 ||
               H5Tequal(dst_id, H5T_IEEE_F32LE) > 0)
      {
         if (H5Tequal(src_id, H5T_STD_I8BE) > 0 ||
             H5Tequal(src_id, H5T_STD_I8LE) > 0)
            *(float *)dst_buf = *(signed char *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U8BE) ||
                  H5Tequal(src_id, H5T_STD_U8LE) > 0)
            *(float *)dst_buf = (unsigned char)*(float *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I16BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I16LE) > 0)
            *(float *)dst_buf = *(signed short *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U16BE) ||
                  H5Tequal(src_id, H5T_STD_U16LE) > 0)
            *(float *)dst_buf = *(unsigned short *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I32BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I32LE) > 0)
            *(float *)dst_buf = *(signed int *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U32BE) ||
                  H5Tequal(src_id, H5T_STD_U32LE) > 0)
            *(float *)dst_buf = *(unsigned int *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I64BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I64LE) > 0)
            *(float *)dst_buf = *(signed long long *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U64BE) ||
                  H5Tequal(src_id, H5T_STD_U64LE) > 0)
            *(float *)dst_buf = *(unsigned long long *)src_buf;
         else if (H5Tequal(src_id, H5T_IEEE_F32BE) > 0 ||
                  H5Tequal(src_id, H5T_IEEE_F32LE) > 0)
            *(float *)dst_buf = *(float *)src_buf;
         else if (H5Tequal(src_id, H5T_IEEE_F64BE) ||
                  H5Tequal(src_id, H5T_IEEE_F64LE) > 0)
            *(float *)dst_buf = *(double *)src_buf;
         else
         {
            printf("Unknown type!\n");
            return H5T_CONV_UNHANDLED;
         }       
      }
      else if (H5Tequal(dst_id, H5T_IEEE_F64BE) ||
               H5Tequal(dst_id, H5T_IEEE_F64LE) > 0)
      {
         if (H5Tequal(src_id, H5T_STD_I8BE) > 0 ||
             H5Tequal(src_id, H5T_STD_I8LE) > 0)
            *(double *)dst_buf = *(signed char *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U8BE) ||
                  H5Tequal(src_id, H5T_STD_U8LE) > 0)
            *(double *)dst_buf = (unsigned char)*(float *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I16BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I16LE) > 0)
            *(double *)dst_buf = *(signed short *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U16BE) ||
                  H5Tequal(src_id, H5T_STD_U16LE) > 0)
            *(double *)dst_buf = *(unsigned short *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I32BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I32LE) > 0)
            *(double *)dst_buf = *(signed int *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U32BE) ||
                  H5Tequal(src_id, H5T_STD_U32LE) > 0)
            *(double *)dst_buf = *(unsigned int *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_I64BE) > 0 ||
                  H5Tequal(src_id, H5T_STD_I64LE) > 0)
            *(double *)dst_buf = *(signed long long *)src_buf;
         else if (H5Tequal(src_id, H5T_STD_U64BE) ||
                  H5Tequal(src_id, H5T_STD_U64LE) > 0)
            *(double *)dst_buf = *(unsigned long long *)src_buf;
         else if (H5Tequal(src_id, H5T_IEEE_F32BE) > 0 ||
                  H5Tequal(src_id, H5T_IEEE_F32LE) > 0)
            *(double *)dst_buf = *(float *)src_buf;
         else if (H5Tequal(src_id, H5T_IEEE_F64BE) ||
                  H5Tequal(src_id, H5T_IEEE_F64LE) > 0)
            *(double *)dst_buf = *(double *)src_buf;
         else
         {
            printf("Unknown type!\n");
            return H5T_CONV_UNHANDLED;
         }
      }
      else
      {
         printf("Unknown type!\n");
         return H5T_CONV_UNHANDLED;
      }  

      (*(int *)user_data)++;
      return H5T_CONV_HANDLED;
   }

   return H5T_CONV_UNHANDLED;
}

int
main()
{
   hid_t fileid, grpid, spaceid, typeid, datasetid, schar_datasetid;
   hid_t float_datasetid;
   hid_t xfer_plistid;
   int int_data_out[DIM1_LEN] = {-666, 0, 666};
   unsigned char uchar_data_out[DIM1_LEN] = {0, 128, 255};
   unsigned char uchar_data_in[DIM1_LEN];
   signed char schar_fill_value = 127;
   int overflow_count = 0;
   float float_data_out[DIM1_LEN] = {-.1, 9999.99, 100.001}, 
float_data_in[DIM1_LEN];
/*   float float_data_out2[DIM1_LEN] = {-2147483649.0, -2147483649.0, 
2147483648.0};*/
   float float_data_out2[DIM1_LEN] = {(float)INT_MIN - 1.0, (float)INT_MIN - 
1.0, (float)INT_MAX + 129.0};
   hsize_t dims[1];
   int i;

   printf("\n*** Checking HDF5 data type conversions.\n");
   printf("*** creating test file...");

   /* Open file and create group. */
   if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, 
                           H5P_DEFAULT)) < 0) ERR;
   if ((grpid = H5Gcreate(fileid, GRP_NAME, 0)) < 0) ERR;

   /* Create a data transfer property lists, and set up an exception
    * function which will be called whenever a conversion exception
    * happens (i.e. an overflow, truncation, or loss of precision
    * during data conversion). */
   if ((xfer_plistid = H5Pcreate(H5P_DATASET_XFER)) < 0) ERR;
   if (H5Pset_type_conv_cb(xfer_plistid, except_func, &overflow_count) < 0) ERR;

   /* Write small arrays of ints, signed chars, and floats. Just to be
    * tricky, write the uchar data out to the schar dataset. This will
    * cause overflows. */
   dims[0] = DIM1_LEN;
   if ((spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
   if ((datasetid = H5Dcreate(grpid, INT_VAR_NAME, H5T_NATIVE_INT, 
                              spaceid, H5P_DEFAULT)) < 0) ERR;
   if ((schar_datasetid = H5Dcreate(grpid, SCHAR_VAR_NAME, H5T_NATIVE_SCHAR, 
                                    spaceid, H5P_DEFAULT)) < 0) ERR;
   if ((float_datasetid = H5Dcreate(grpid, FLOAT_VAR_NAME, H5T_NATIVE_FLOAT, 
                                    spaceid, H5P_DEFAULT)) < 0) ERR;
   if (H5Dwrite(datasetid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, xfer_plistid, 
                int_data_out) < 0) ERR;
   if (H5Dwrite(schar_datasetid, H5T_NATIVE_UCHAR, H5S_ALL, H5S_ALL, 
                xfer_plistid, uchar_data_out) < 0) ERR;
   if (H5Dwrite(float_datasetid, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, 
                xfer_plistid, float_data_out) < 0) ERR;

   /* This should have produced 2 overflows. */
   if (overflow_count != 2) ERR;
   overflow_count = 0;

   if (H5Dclose(datasetid) < 0 ||
       H5Dclose(schar_datasetid) < 0 ||
       H5Dclose(float_datasetid) < 0 ||
       H5Sclose(spaceid) < 0) ERR;

   SUMMARIZE_ERR;

   /* Make sure ints can be converted into floats. Read the int
    * dataset into an array of floats, and make sure the results match
    * netcdf's conversion rules (which are exactly the C typecasting
    * rules). */
   printf("*** reading int dataset as floats...");
   if ((datasetid = H5Dopen(grpid, INT_VAR_NAME)) < 0) ERR;
   if (H5Dread(datasetid, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, 
               H5P_DEFAULT, float_data_in) < 0) ERR;
   if (H5Dclose(datasetid) < 0) ERR;
   for (i=0; i<DIM1_LEN; i++)
      if (float_data_in[i] != (float)int_data_out[i]) ERR;

   /* This should have produced no overflows. */
   if (overflow_count != 0) ERR;

   SUMMARIZE_ERR;

   /* Make sure floats can be converted into schars. Read the float
    * dataset into an array of uchar. */
   printf("*** reading float dataset as uchars...");
   if ((datasetid = H5Dopen(grpid, FLOAT_VAR_NAME)) < 0) ERR;
   if (H5Dread(datasetid, H5T_NATIVE_UCHAR, H5S_ALL, H5S_ALL, 
               xfer_plistid, uchar_data_in) < 0) ERR;
   if (H5Dclose(datasetid) < 0) ERR;

   /* This should have produced 2 overflows. */
   if (overflow_count != 2) ERR;
   overflow_count = 0;

   for (i=0; i<DIM1_LEN; i++)
      if (uchar_data_in[i] != (unsigned char)float_data_out[i]) ERR;

   SUMMARIZE_ERR;
   overflow_count = 0;

   /* Now write three out of range floats to the int. This should
    * generate three exceptions. */
   printf("*** writing out of range floats to int dataset...\n");
   for (i = 0; i < DIM1_LEN; i++)
   {
      printf("float_data_out2[%d]=%f\n", i, float_data_out2[i]);
      printf("(int)float_data_out2[%d]=%d\n", i, (int)float_data_out2[i]);
   }
   if ((datasetid = H5Dopen(grpid, INT_VAR_NAME)) < 0) ERR;
   if (H5Dwrite(datasetid, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, 
               xfer_plistid, float_data_out2) < 0) ERR;
   if (H5Dclose(datasetid) < 0) ERR;

   /* This should cause three overflows. */
   printf("overflow_count=%d\n", overflow_count);
   if (overflow_count != 3) ERR;
   overflow_count = 0;

   
   SUMMARIZE_ERR;

   /* Close up shop. */
   if (H5Fclose(fileid) < 0 ||
       H5Gclose(grpid) < 0) ERR;

   /* Print out our number of errors, if any, and exit badly. */
   if (total_err)
   {
      printf("%d errors detected! Sorry!\n", total_err);
      return 2;
   }
   
   printf("*** Tests successful!\n");
   return 0;
}


tests.h:

/* This is part of the netCDF package.
   Copyright 2005 University Corporation for Atmospheric Research/Unidata
   See COPYRIGHT file for conditions of use.

   Common includes, defines, etc., for test code in the libsrc4
   directory.

   $Id: tests.h,v 1.6 2005/06/06 20:36:22 ed Exp $
*/
#ifndef _NC4_TESTS_
#define _NC4_TESTS_

#include <config.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "error.h"

int total_err = 0, err = 0;

/* This is handy for print statements. */
char *format_name[] = {"", "classic", "64-bit offset", "netCDF-4", "netCDF-4 
strict NC3"};

#define ERR do { \
fflush(stdout); /* Make sure our stdout is synced with stderr. */ \
err++; \
fprintf(stderr, "unexpected result, %s, line: %d\n", __FILE__, __LINE__); \
} while (0)

#define SUMMARIZE_ERR do { \
   if (err) \
   { \
      printf("%d failures\n", err); \
      total_err += err; \
      err = 0; \
   } \
   else \
      printf("ok.\n"); \
} while (0)


#endif /* _NC4_TESTS_ */

-- 
Ed Hartnett  -- ed@xxxxxxxxxxxxxxxx