diff --git a/src/endian.c b/src/endian.c index 1327a3e7..e4a58573 100644 --- a/src/endian.c +++ b/src/endian.c @@ -183,8 +183,8 @@ Mat_uint16Swap(mat_uint16_t *a) /** @brief swap the bytes of a 4 byte single-precision float * @ingroup mat_internal - * @param a pointer to integer to swap - * @return the swapped integer + * @param a pointer to integer? to swap + * @return the swapped integer? */ float Mat_floatSwap(float *a) @@ -205,8 +205,8 @@ Mat_floatSwap(float *a) /** @brief swap the bytes of a 4 or 8 byte double-precision float * @ingroup mat_internal - * @param a pointer to integer to swap - * @return the swapped integer + * @param a pointer to integer? to swap + * @return the swapped integer? */ double Mat_doubleSwap(double *a) diff --git a/src/read_data.c b/src/read_data.c index 762dc95a..aa9d72ca 100644 --- a/src/read_data.c +++ b/src/read_data.c @@ -34,21 +34,31 @@ #if HAVE_ZLIB #include #endif +#include #include +#include #include #include #include #include #include -#define READ_DATA_NOSWAP(T) \ +#define READ_DATA_NOSWAP(T, TT, RoundFunc) \ do { \ + TT min_ = (TT)READ_TYPE_MIN; \ + TT max_ = (TT)READ_TYPE_MAX; \ const size_t block_size = READ_BLOCK_SIZE / data_size; \ if ( len <= block_size ) { \ readcount = fread(v, data_size, len, (FILE *)mat->fp); \ if ( readcount == len ) { \ for ( i = 0; i < len; i++ ) { \ - data[i] = (T)v[i]; \ + TT val_ = v[i]; \ + val_ = RoundFunc(val_); \ + if (val_ >= min_ && val_ <= max_) { \ + data[i] = (T)val_; \ + } else { \ + break; \ + } \ } \ } \ } else { \ @@ -60,7 +70,14 @@ readcount += j; \ if ( j == block_size ) { \ for ( j = 0; j < block_size; j++ ) { \ - data[i + j] = (T)v[j]; \ + TT val_ = v[j]; \ + val_ = RoundFunc(val_); \ + if (val_ >= min_ && val_ <= max_) { \ + data[i + j] = (T)val_; \ + } else { \ + err_ = 1; \ + break; \ + } \ } \ } else { \ err_ = 1; \ @@ -72,22 +89,37 @@ readcount += j; \ if ( j == len - i ) { \ for ( j = 0; j < len - i; j++ ) { \ - data[i + j] = (T)v[j]; \ + TT val_ = v[j]; \ + val_ = RoundFunc(val_); \ + if (val_ >= min_ && val_ <= max_) { \ + data[i + j] = (T)val_; \ + } else { \ + err_ = 1; \ + break; \ + } \ } \ } \ } \ } \ } while ( 0 ) -#define READ_DATA(T, SwapFunc) \ +#define READ_DATA(T, TT, SwapFunc, RoundFunc) \ do { \ + TT min_ = (TT)READ_TYPE_MIN; \ + TT max_ = (TT)READ_TYPE_MAX; \ if ( mat->byteswap ) { \ const size_t block_size = READ_BLOCK_SIZE / data_size; \ if ( len <= block_size ) { \ readcount = fread(v, data_size, len, (FILE *)mat->fp); \ if ( readcount == len ) { \ for ( i = 0; i < len; i++ ) { \ - data[i] = (T)SwapFunc(&v[i]); \ + TT swapped_ = SwapFunc(&v[i]); \ + swapped_ = RoundFunc(swapped_); \ + if (swapped_ >= min_ && swapped_ <= max_) { \ + data[i] = (T)swapped_; \ + } else { \ + break; \ + } \ } \ } \ } else { \ @@ -99,7 +131,14 @@ readcount += j; \ if ( j == block_size ) { \ for ( j = 0; j < block_size; j++ ) { \ - data[i + j] = (T)SwapFunc(&v[j]); \ + TT swapped_ = SwapFunc(&v[j]); \ + swapped_ = RoundFunc(swapped_); \ + if (swapped_ >= min_ && swapped_ <= max_) { \ + data[i + j] = (T)swapped_; \ + } else { \ + err_ = 1; \ + break; \ + } \ } \ } else { \ err_ = 1; \ @@ -111,13 +150,19 @@ readcount += j; \ if ( j == len - i ) { \ for ( j = 0; j < len - i; j++ ) { \ - data[i + j] = (T)SwapFunc(&v[j]); \ + TT swapped_ = SwapFunc(&v[j]); \ + if (swapped_ >= min_ && swapped_ <= max_) { \ + data[i + j] = (T)swapped_; \ + } else { \ + err_ = 1; \ + break; \ + } \ } \ } \ } \ } \ } else { \ - READ_DATA_NOSWAP(T); \ + READ_DATA_NOSWAP(T, TT, RoundFunc); \ } \ } while ( 0 ) @@ -198,6 +243,8 @@ #define READ_TYPE_UINT8 10 #define READ_TYPE double +#define READ_TYPE_MIN (-DBL_MAX) +#define READ_TYPE_MAX DBL_MAX #define READ_TYPE_TYPE READ_TYPE_DOUBLE #define READ_TYPED_FUNC1 ReadDoubleData #define READ_TYPED_FUNC2 ReadCompressedDoubleData @@ -208,6 +255,8 @@ #undef READ_TYPED_FUNC2 #define READ_TYPE float +#define READ_TYPE_MIN (-FLT_MAX) +#define READ_TYPE_MAX FLT_MAX #define READ_TYPE_TYPE READ_TYPE_SINGLE #define READ_TYPED_FUNC1 ReadSingleData #define READ_TYPED_FUNC2 ReadCompressedSingleData @@ -219,6 +268,8 @@ #ifdef HAVE_MAT_INT64_T #define READ_TYPE mat_int64_t +#define READ_TYPE_MIN INT64_MIN +#define READ_TYPE_MAX INT64_MAX #define READ_TYPE_TYPE READ_TYPE_INT64 #define READ_TYPED_FUNC1 ReadInt64Data #define READ_TYPED_FUNC2 ReadCompressedInt64Data @@ -231,6 +282,8 @@ #ifdef HAVE_MAT_UINT64_T #define READ_TYPE mat_uint64_t +#define READ_TYPE_MIN 0 +#define READ_TYPE_MAX UINT64_MAX #define READ_TYPE_TYPE READ_TYPE_UINT64 #define READ_TYPED_FUNC1 ReadUInt64Data #define READ_TYPED_FUNC2 ReadCompressedUInt64Data @@ -242,6 +295,8 @@ #endif /* HAVE_MAT_UINT64_T */ #define READ_TYPE mat_int32_t +#define READ_TYPE_MIN INT32_MIN +#define READ_TYPE_MAX INT32_MAX #define READ_TYPE_TYPE READ_TYPE_INT32 #define READ_TYPED_FUNC1 ReadInt32Data #define READ_TYPED_FUNC2 ReadCompressedInt32Data @@ -252,6 +307,8 @@ #undef READ_TYPED_FUNC2 #define READ_TYPE mat_uint32_t +#define READ_TYPE_MIN 0 +#define READ_TYPE_MAX UINT32_MAX #define READ_TYPE_TYPE READ_TYPE_UINT32 #define READ_TYPED_FUNC1 ReadUInt32Data #define READ_TYPED_FUNC2 ReadCompressedUInt32Data @@ -262,6 +319,8 @@ #undef READ_TYPED_FUNC2 #define READ_TYPE mat_int16_t +#define READ_TYPE_MIN INT16_MIN +#define READ_TYPE_MAX INT16_MAX #define READ_TYPE_TYPE READ_TYPE_INT16 #define READ_TYPED_FUNC1 ReadInt16Data #define READ_TYPED_FUNC2 ReadCompressedInt16Data @@ -272,6 +331,8 @@ #undef READ_TYPED_FUNC2 #define READ_TYPE mat_uint16_t +#define READ_TYPE_MIN 0 +#define READ_TYPE_MAX UINT16_MAX #define READ_TYPE_TYPE READ_TYPE_UINT16 #define READ_TYPED_FUNC1 ReadUInt16Data #define READ_TYPED_FUNC2 ReadCompressedUInt16Data @@ -282,6 +343,8 @@ #undef READ_TYPED_FUNC2 #define READ_TYPE mat_int8_t +#define READ_TYPE_MIN INT8_MIN +#define READ_TYPE_MAX INT8_MAX #define READ_TYPE_TYPE READ_TYPE_INT8 #define READ_TYPED_FUNC1 ReadInt8Data #define READ_TYPED_FUNC2 ReadCompressedInt8Data @@ -292,6 +355,8 @@ #undef READ_TYPED_FUNC2 #define READ_TYPE mat_uint8_t +#define READ_TYPE_MIN 0 +#define READ_TYPE_MAX UINT8_MAX #define READ_TYPE_TYPE READ_TYPE_UINT8 #define READ_TYPED_FUNC1 ReadUInt8Data #define READ_TYPED_FUNC2 ReadCompressedUInt8Data @@ -360,6 +425,12 @@ ReadCompressedCharData(mat_t *mat, z_streamp z, void *data, enum matio_types dat } #endif +static mat_uint16_t +NOP_UINT16(mat_uint16_t value) +{ + return value; +} + size_t ReadCharData(mat_t *mat, void *_data, enum matio_types data_type, size_t len) { @@ -383,7 +454,7 @@ ReadCharData(mat_t *mat, void *_data, enum matio_types data_type, size_t len) size_t i, readcount; mat_uint16_t *data = (mat_uint16_t *)_data; mat_uint16_t v[READ_BLOCK_SIZE / sizeof(mat_uint16_t)]; - READ_DATA(mat_uint16_t, Mat_uint16Swap); + READ_DATA(mat_uint16_t, mat_uint16_t, Mat_uint16Swap, NOP_UINT16); err = Mul(&nBytes, readcount, data_size); break; } diff --git a/src/read_data_impl.h b/src/read_data_impl.h index 63e3db49..48305c70 100644 --- a/src/read_data_impl.h +++ b/src/read_data_impl.h @@ -40,6 +40,18 @@ #define READ_TYPE_UINT64_DATA CAT(READ_TYPED_FUNC1, UInt64) #endif /* HAVE_MAT_UINT64_T */ +static READ_TYPE +CAT(Round, READ_TYPE)(READ_TYPE value) +{ +#if READ_TYPE_TYPE == READ_TYPE_DOUBLE + return round(value); +#elif READ_TYPE_TYPE == READ_TYPE_SINGLE + return roundf(value); +#else + return value; +#endif +} + static size_t READ_TYPE_DOUBLE_DATA(mat_t *mat, READ_TYPE *data, size_t len) { @@ -56,7 +68,7 @@ READ_TYPE_DOUBLE_DATA(mat_t *mat, READ_TYPE *data, size_t len) size_t i; const size_t data_size = sizeof(double); double v[READ_BLOCK_SIZE / sizeof(double)]; - READ_DATA(READ_TYPE, Mat_doubleSwap); + READ_DATA(READ_TYPE, double, Mat_doubleSwap, CAT(Round, READ_TYPE)); #endif return readcount; } @@ -77,7 +89,7 @@ READ_TYPE_SINGLE_DATA(mat_t *mat, READ_TYPE *data, size_t len) size_t i; const size_t data_size = sizeof(float); float v[READ_BLOCK_SIZE / sizeof(float)]; - READ_DATA(READ_TYPE, Mat_floatSwap); + READ_DATA(READ_TYPE, float, Mat_floatSwap, CAT(Round, READ_TYPE)); #endif return readcount; } @@ -98,7 +110,7 @@ READ_TYPE_INT32_DATA(mat_t *mat, READ_TYPE *data, size_t len) size_t i; const size_t data_size = sizeof(mat_int32_t); mat_int32_t v[READ_BLOCK_SIZE / sizeof(mat_int32_t)]; - READ_DATA(READ_TYPE, Mat_int32Swap); + READ_DATA(READ_TYPE, mat_int32_t, Mat_int32Swap, CAT(Round, READ_TYPE)); #endif return readcount; } @@ -119,7 +131,7 @@ READ_TYPE_UINT32_DATA(mat_t *mat, READ_TYPE *data, size_t len) size_t i; const size_t data_size = sizeof(mat_uint32_t); mat_uint32_t v[READ_BLOCK_SIZE / sizeof(mat_uint32_t)]; - READ_DATA(READ_TYPE, Mat_uint32Swap); + READ_DATA(READ_TYPE, mat_uint32_t, Mat_uint32Swap, CAT(Round, READ_TYPE)); #endif return readcount; } @@ -140,7 +152,7 @@ READ_TYPE_INT16_DATA(mat_t *mat, READ_TYPE *data, size_t len) size_t i; const size_t data_size = sizeof(mat_int16_t); mat_int16_t v[READ_BLOCK_SIZE / sizeof(mat_int16_t)]; - READ_DATA(READ_TYPE, Mat_int16Swap); + READ_DATA(READ_TYPE, mat_int16_t, Mat_int16Swap, CAT(Round, READ_TYPE)); #endif return readcount; } @@ -161,7 +173,7 @@ READ_TYPE_UINT16_DATA(mat_t *mat, READ_TYPE *data, size_t len) size_t i; const size_t data_size = sizeof(mat_uint16_t); mat_uint16_t v[READ_BLOCK_SIZE / sizeof(mat_uint16_t)]; - READ_DATA(READ_TYPE, Mat_uint16Swap); + READ_DATA(READ_TYPE, mat_uint16_t, Mat_uint16Swap, CAT(Round, READ_TYPE)); #endif return readcount; } @@ -176,7 +188,7 @@ READ_TYPE_INT8_DATA(mat_t *mat, READ_TYPE *data, size_t len) size_t i; const size_t data_size = sizeof(mat_int8_t); mat_int8_t v[READ_BLOCK_SIZE / sizeof(mat_int8_t)]; - READ_DATA_NOSWAP(READ_TYPE); + READ_DATA_NOSWAP(READ_TYPE, mat_int8_t, CAT(Round, READ_TYPE)); #endif return readcount; } @@ -191,7 +203,7 @@ READ_TYPE_UINT8_DATA(mat_t *mat, READ_TYPE *data, size_t len) size_t i; const size_t data_size = sizeof(mat_uint8_t); mat_uint8_t v[READ_BLOCK_SIZE / sizeof(mat_uint8_t)]; - READ_DATA_NOSWAP(READ_TYPE); + READ_DATA_NOSWAP(READ_TYPE, mat_uint8_t, CAT(Round, READ_TYPE)); #endif return readcount; } @@ -213,7 +225,7 @@ READ_TYPE_INT64_DATA(mat_t *mat, READ_TYPE *data, size_t len) size_t i; const size_t data_size = sizeof(mat_int64_t); mat_int64_t v[READ_BLOCK_SIZE / sizeof(mat_int64_t)]; - READ_DATA(READ_TYPE, Mat_int64Swap); + READ_DATA(READ_TYPE, mat_int64_t, Mat_int64Swap, CAT(Round, READ_TYPE)); #endif return readcount; } @@ -236,7 +248,7 @@ READ_TYPE_UINT64_DATA(mat_t *mat, READ_TYPE *data, size_t len) size_t i; const size_t data_size = sizeof(mat_uint64_t); mat_uint64_t v[READ_BLOCK_SIZE / sizeof(mat_uint64_t)]; - READ_DATA(READ_TYPE, Mat_uint64Swap); + READ_DATA(READ_TYPE, mat_uint64_t, Mat_uint64Swap, CAT(Round, READ_TYPE)); #endif return readcount; }