Skip to content

Commit

Permalink
Add GDALIsValueExactAs()
Browse files Browse the repository at this point in the history
  • Loading branch information
rouault committed Sep 1, 2024
1 parent 2ca0503 commit f5c3e40
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 0 deletions.
100 changes: 100 additions & 0 deletions autotest/cpp/test_gdal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,106 @@ TEST_F(test_gdal, GDALIsValueExactAs)
GDALIsValueExactAs<double>(std::numeric_limits<double>::quiet_NaN()));
}

// Test GDALIsValueExactAs()
TEST_F(test_gdal, GDALIsValueExactAs_C_func)
{
EXPECT_TRUE(GDALIsValueExactAs(0, GDT_Byte));
EXPECT_TRUE(GDALIsValueExactAs(255, GDT_Byte));
EXPECT_FALSE(GDALIsValueExactAs(-1, GDT_Byte));
EXPECT_FALSE(GDALIsValueExactAs(256, GDT_Byte));
EXPECT_FALSE(GDALIsValueExactAs(0.5, GDT_Byte));

EXPECT_TRUE(GDALIsValueExactAs(-128, GDT_Int8));
EXPECT_TRUE(GDALIsValueExactAs(127, GDT_Int8));
EXPECT_FALSE(GDALIsValueExactAs(-129, GDT_Int8));
EXPECT_FALSE(GDALIsValueExactAs(128, GDT_Int8));
EXPECT_FALSE(GDALIsValueExactAs(0.5, GDT_Int8));

EXPECT_TRUE(GDALIsValueExactAs(0, GDT_UInt16));
EXPECT_TRUE(GDALIsValueExactAs(65535, GDT_UInt16));
EXPECT_FALSE(GDALIsValueExactAs(-1, GDT_UInt16));
EXPECT_FALSE(GDALIsValueExactAs(65536, GDT_UInt16));
EXPECT_FALSE(GDALIsValueExactAs(0.5, GDT_UInt16));

EXPECT_TRUE(GDALIsValueExactAs(-32768, GDT_Int16));
EXPECT_TRUE(GDALIsValueExactAs(32767, GDT_Int16));
EXPECT_FALSE(GDALIsValueExactAs(-32769, GDT_Int16));
EXPECT_FALSE(GDALIsValueExactAs(32768, GDT_Int16));
EXPECT_FALSE(GDALIsValueExactAs(0.5, GDT_Int16));

EXPECT_TRUE(GDALIsValueExactAs(std::numeric_limits<uint32_t>::lowest(),
GDT_UInt32));
EXPECT_TRUE(
GDALIsValueExactAs(std::numeric_limits<uint32_t>::max(), GDT_UInt32));
EXPECT_FALSE(GDALIsValueExactAs(
std::numeric_limits<uint32_t>::lowest() - 1.0, GDT_UInt32));
EXPECT_FALSE(GDALIsValueExactAs(std::numeric_limits<uint32_t>::max() + 1.0,
GDT_UInt32));
EXPECT_FALSE(GDALIsValueExactAs(0.5, GDT_UInt32));

EXPECT_TRUE(
GDALIsValueExactAs(std::numeric_limits<int32_t>::lowest(), GDT_Int32));
EXPECT_TRUE(
GDALIsValueExactAs(std::numeric_limits<int32_t>::max(), GDT_Int32));
EXPECT_FALSE(GDALIsValueExactAs(
std::numeric_limits<int32_t>::lowest() - 1.0, GDT_Int32));
EXPECT_FALSE(GDALIsValueExactAs(std::numeric_limits<int32_t>::max() + 1.0,
GDT_Int32));
EXPECT_FALSE(GDALIsValueExactAs(0.5, GDT_Int32));

EXPECT_TRUE(GDALIsValueExactAs(
static_cast<double>(std::numeric_limits<uint64_t>::lowest()),
GDT_UInt64));
// (1 << 64) - 2048
EXPECT_TRUE(GDALIsValueExactAs(18446744073709549568.0, GDT_UInt64));
EXPECT_FALSE(GDALIsValueExactAs(
static_cast<double>(std::numeric_limits<uint64_t>::lowest()) - 1.0,
GDT_UInt64));
// (1 << 64)
EXPECT_FALSE(GDALIsValueExactAs(18446744073709551616.0, GDT_UInt64));
EXPECT_FALSE(GDALIsValueExactAs(0.5, GDT_UInt64));

EXPECT_TRUE(GDALIsValueExactAs(
static_cast<double>(std::numeric_limits<int64_t>::lowest()),
GDT_Int64));
// (1 << 63) - 1024
EXPECT_TRUE(GDALIsValueExactAs(9223372036854774784.0, GDT_Int64));
EXPECT_FALSE(GDALIsValueExactAs(
static_cast<double>(std::numeric_limits<int64_t>::lowest()) - 2048.0,
GDT_Int64));
// (1 << 63) - 512
EXPECT_FALSE(GDALIsValueExactAs(9223372036854775296.0, GDT_Int64));
EXPECT_FALSE(GDALIsValueExactAs(0.5, GDT_Int64));

EXPECT_TRUE(
GDALIsValueExactAs(-std::numeric_limits<float>::max(), GDT_Float32));
EXPECT_TRUE(
GDALIsValueExactAs(std::numeric_limits<float>::max(), GDT_Float32));
EXPECT_TRUE(GDALIsValueExactAs(-std::numeric_limits<float>::infinity(),
GDT_Float32));
EXPECT_TRUE(GDALIsValueExactAs(std::numeric_limits<float>::infinity(),
GDT_Float32));
EXPECT_TRUE(GDALIsValueExactAs(std::numeric_limits<double>::quiet_NaN(),
GDT_Float32));
EXPECT_TRUE(
!GDALIsValueExactAs(-std::numeric_limits<double>::max(), GDT_Float32));
EXPECT_TRUE(
!GDALIsValueExactAs(std::numeric_limits<double>::max(), GDT_Float32));

EXPECT_TRUE(GDALIsValueExactAs(-std::numeric_limits<double>::infinity(),
GDT_Float64));
EXPECT_TRUE(GDALIsValueExactAs(std::numeric_limits<double>::infinity(),
GDT_Float64));
EXPECT_TRUE(
GDALIsValueExactAs(-std::numeric_limits<double>::max(), GDT_Float64));
EXPECT_TRUE(
GDALIsValueExactAs(std::numeric_limits<double>::max(), GDT_Float64));
EXPECT_TRUE(GDALIsValueExactAs(std::numeric_limits<double>::quiet_NaN(),
GDT_Float64));

EXPECT_TRUE(GDALIsValueExactAs(0, GDT_CInt16));
}

#ifdef _MSC_VER
#pragma warning(pop)
#endif
Expand Down
1 change: 1 addition & 0 deletions gcore/gdal.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ GDALDataType CPL_DLL CPL_STDCALL GDALFindDataTypeForValue(double dValue,
int bComplex);
double CPL_DLL GDALAdjustValueToDataType(GDALDataType eDT, double dfValue,
int *pbClamped, int *pbRounded);
bool CPL_DLL GDALIsValueExactAs(double dfValue, GDALDataType eDT);
GDALDataType CPL_DLL CPL_STDCALL GDALGetNonComplexDataType(GDALDataType);
int CPL_DLL CPL_STDCALL GDALDataTypeIsConversionLossy(GDALDataType eTypeFrom,
GDALDataType eTypeTo);
Expand Down
52 changes: 52 additions & 0 deletions gcore/gdal_misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -938,6 +938,58 @@ double GDALAdjustValueToDataType(GDALDataType eDT, double dfValue,
return dfValue;
}

/************************************************************************/
/* GDALIsValueExactAs() */
/************************************************************************/

/**
* \brief Check whether the provided value can be exactly represented in a
* data type.
*
* Only implemented for non-complex data types
*
* @param dfValue value to check.
* @param eDT target data type.
*
* @return true if the provided value can be exactly represented in the
* data type.
* @since GDAL 3.10
*/
bool GDALIsValueExactAs(double dfValue, GDALDataType eDT)
{
switch (eDT)
{
case GDT_Byte:
return GDALIsValueExactAs<uint8_t>(dfValue);
case GDT_Int8:
return GDALIsValueExactAs<int8_t>(dfValue);
case GDT_UInt16:
return GDALIsValueExactAs<uint16_t>(dfValue);
case GDT_Int16:
return GDALIsValueExactAs<int16_t>(dfValue);
case GDT_UInt32:
return GDALIsValueExactAs<uint32_t>(dfValue);
case GDT_Int32:
return GDALIsValueExactAs<int32_t>(dfValue);
case GDT_UInt64:
return GDALIsValueExactAs<uint64_t>(dfValue);
case GDT_Int64:
return GDALIsValueExactAs<int64_t>(dfValue);
case GDT_Float32:
return GDALIsValueExactAs<float>(dfValue);
case GDT_Float64:
return true;
case GDT_Unknown:
case GDT_CInt16:
case GDT_CInt32:
case GDT_CFloat32:
case GDT_CFloat64:
case GDT_TypeCount:
break;
}
return true;
}

/************************************************************************/
/* GDALGetNonComplexDataType() */
/************************************************************************/
Expand Down

0 comments on commit f5c3e40

Please sign in to comment.