diff --git a/tensorflow_serving/util/json_tensor.cc b/tensorflow_serving/util/json_tensor.cc index ea387a3d72a..a0870b812df 100644 --- a/tensorflow_serving/util/json_tensor.cc +++ b/tensorflow_serving/util/json_tensor.cc @@ -15,6 +15,7 @@ limitations under the License. #include "tensorflow_serving/util/json_tensor.h" +#include #include #include #include @@ -209,15 +210,26 @@ Status LossyDecimalError(const rapidjson::Value& val, const string& target) { template bool IsLosslessDecimal(const rapidjson::Value& val) { static_assert(std::is_same::value || std::is_same::value, - "Only floating-point value types are supported."); + "Only floating point value types are supported."); + static_assert(std::numeric_limits::radix == 2, + "Floating point type must have base 2."); // Note, we use GetDouble() for both types as std::isfinite() returns false // for decimal values that do not fit in float (due to the static_cast<> used // in converting double to float in GetFloat() call). if (!std::isfinite(val.GetDouble())) return true; - if (std::is_same::value) return val.IsLosslessFloat(); - return val.IsLosslessDouble(); + // Maximum integer value that can be represented by the floating type. + static constexpr int64 kMaxInt = (1LL << std::numeric_limits::digits) - 1; + + if (val.IsUint64()) { + return val.GetUint64() <= kMaxInt; + } + if (val.IsInt64()) { + return std::abs(val.GetInt64()) <= kMaxInt; + } + return val.GetDouble() <= std::numeric_limits::max() && + val.GetDouble() >= std::numeric_limits::lowest(); } // Adds a JSON value to Tensor. Returns error if value cannot be converted diff --git a/tensorflow_serving/util/json_tensor_test.cc b/tensorflow_serving/util/json_tensor_test.cc index 1d8edf219f6..9edc46e1cb1 100644 --- a/tensorflow_serving/util/json_tensor_test.cc +++ b/tensorflow_serving/util/json_tensor_test.cc @@ -81,7 +81,7 @@ TEST(JsontensorTest, SingleUnnamedTensor) { )")); } -TEST(JsontensorTest, IntegerInputForFloatTensor) { +TEST(JsontensorTest, MixedInputForFloatTensor) { TensorInfoMap infomap; ASSERT_TRUE( TextFormat::ParseFromString("dtype: DT_FLOAT", &infomap["default"])); @@ -90,7 +90,7 @@ TEST(JsontensorTest, IntegerInputForFloatTensor) { JsonPredictRequestFormat format; TF_EXPECT_OK(FillPredictRequestFromJson(R"( { - "instances": [1, 2, 3, 4, 5] + "instances": [1, 2.0, 3, 4, 5.003, 0.007, 0.0] })", getmap(infomap), &req, &format)); auto tmap = req.inputs(); @@ -98,16 +98,18 @@ TEST(JsontensorTest, IntegerInputForFloatTensor) { EXPECT_EQ(format, JsonPredictRequestFormat::kRow); EXPECT_THAT(tmap["default"], EqualsProto(R"( dtype: DT_FLOAT - tensor_shape { dim { size: 5 } } + tensor_shape { dim { size: 7 } } float_val: 1 - float_val: 2 + float_val: 2.0 float_val: 3 float_val: 4 - float_val: 5 + float_val: 5.003 + float_val: 0.007 + float_val: 0.0 )")); } -TEST(JsontensorTest, IntegerInputForDoubleTensor) { +TEST(JsontensorTest, MixedInputForDoubleTensor) { TensorInfoMap infomap; ASSERT_TRUE( TextFormat::ParseFromString("dtype: DT_DOUBLE", &infomap["default"])); @@ -116,7 +118,7 @@ TEST(JsontensorTest, IntegerInputForDoubleTensor) { JsonPredictRequestFormat format; TF_EXPECT_OK(FillPredictRequestFromJson(R"( { - "instances": [1, 2, 3, 4, 5] + "instances": [1.0, 2, 3, 4, 0.662, 0, 0.0] })", getmap(infomap), &req, &format)); auto tmap = req.inputs(); @@ -124,12 +126,14 @@ TEST(JsontensorTest, IntegerInputForDoubleTensor) { EXPECT_EQ(format, JsonPredictRequestFormat::kRow); EXPECT_THAT(tmap["default"], EqualsProto(R"( dtype: DT_DOUBLE - tensor_shape { dim { size: 5 } } - double_val: 1 + tensor_shape { dim { size: 7 } } + double_val: 1.0 double_val: 2 double_val: 3 double_val: 4 - double_val: 5 + double_val: 0.662 + double_val: 0 + double_val: 0.0 )")); }