Skip to content

Commit

Permalink
GDALFindDataTypeForValue(): fix for integer values that can't be repr…
Browse files Browse the repository at this point in the history
…esented as UInt64
  • Loading branch information
rouault committed Sep 1, 2024
1 parent 6b5f015 commit cccdd7c
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 6 deletions.
72 changes: 67 additions & 5 deletions autotest/cpp/test_gdal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,12 +260,74 @@ TEST_F(test_gdal, GDALDataTypeUnion_special_cases)
false /* complex */),
GDT_Int64);

EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Byte, -128, 0), GDT_Int16);
EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Byte, -32768, 0), GDT_Int16);
EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Byte, -32769, 0), GDT_Int32);
EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Float32, -99999, 0), GDT_Float32);
EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Float32, -99999.9876, 0),
EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Byte, -128, false), GDT_Int16);
EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Byte, -32768, false), GDT_Int16);
EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Byte, -32769, false), GDT_Int32);

EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Int8, 127, false), GDT_Int8);
EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Int8, 128, false), GDT_Int16);

EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Int16, 32767, false), GDT_Int16);
EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Int16, 32768, false), GDT_Int32);

EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_UInt16, 65535, false), GDT_UInt16);
EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_UInt16, 65536, false), GDT_UInt32);

EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Int32, INT32_MAX, false),
GDT_Int32);
EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Int32, INT32_MAX + 1.0, false),
GDT_Int64);

EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_UInt32, UINT32_MAX, false),
GDT_UInt32);
EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_UInt32, UINT32_MAX + 1.0, false),
GDT_UInt64);

// (1 << 63) - 1024
EXPECT_EQ(
GDALDataTypeUnionWithValue(GDT_Int64, 9223372036854774784.0, false),
GDT_Int64);
// (1 << 63) - 512
EXPECT_EQ(
GDALDataTypeUnionWithValue(GDT_Int64, 9223372036854775296.0, false),
GDT_Float64);

// (1 << 64) - 2048
EXPECT_EQ(
GDALDataTypeUnionWithValue(GDT_UInt64, 18446744073709549568.0, false),
GDT_UInt64);
// (1 << 64) + 4096
EXPECT_EQ(
GDALDataTypeUnionWithValue(GDT_UInt64, 18446744073709555712.0, false),
GDT_Float64);

EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Float32, -99999, false),
GDT_Float32);
EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Float32, -99999.9876, false),
GDT_Float64);
EXPECT_EQ(GDALDataTypeUnionWithValue(
GDT_Float32, std::numeric_limits<double>::quiet_NaN(), false),
GDT_Float32);
EXPECT_EQ(GDALDataTypeUnionWithValue(
GDT_Float32, -std::numeric_limits<double>::infinity(), false),
GDT_Float32);
EXPECT_EQ(GDALDataTypeUnionWithValue(
GDT_Float32, -std::numeric_limits<double>::infinity(), false),
GDT_Float32);

EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Float64, -99999.9876, false),
GDT_Float64);
EXPECT_EQ(GDALDataTypeUnionWithValue(
GDT_Float64, std::numeric_limits<double>::quiet_NaN(), false),
GDT_Float64);
EXPECT_EQ(GDALDataTypeUnionWithValue(
GDT_Float64, -std::numeric_limits<double>::infinity(), false),
GDT_Float64);
EXPECT_EQ(GDALDataTypeUnionWithValue(
GDT_Float64, -std::numeric_limits<double>::infinity(), false),
GDT_Float64);

EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Unknown, 0, false), GDT_Byte);
}

// Test GDALAdjustValueToDataType()
Expand Down
12 changes: 11 additions & 1 deletion gcore/gdal_misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ GDALDataType CPL_STDCALL GDALDataTypeUnion(GDALDataType eType1,
GDALDataType eType2)

{
if (eType1 == GDT_Unknown)
return eType2;
if (eType2 == GDT_Unknown)
return eType1;

const int panBits[] = {GetDataTypeElementSizeBits(eType1),
GetDataTypeElementSizeBits(eType2)};

Expand Down Expand Up @@ -383,7 +388,12 @@ GDALDataType CPL_STDCALL GDALFindDataType(int nBits, int bSigned, int bFloating,
*/
GDALDataType CPL_STDCALL GDALFindDataTypeForValue(double dValue, int bComplex)
{
const bool bFloating = round(dValue) != dValue;
const bool bFloating =
round(dValue) != dValue ||
dValue >
static_cast<double>(std::numeric_limits<std::uint64_t>::max()) ||
dValue <
static_cast<double>(std::numeric_limits<std::int64_t>::lowest());
const bool bSigned = bFloating || dValue < 0;
const int nBits = GetMinBitsForValue(dValue);

Expand Down

0 comments on commit cccdd7c

Please sign in to comment.