-
-
Notifications
You must be signed in to change notification settings - Fork 6.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix issue#1719 #2044
Fix issue#1719 #2044
Conversation
Is there any reason for the 'use_type' parameter? Or at least I would make its default value 'true'. I see no use case why we should serialize something as double instead of float when the actual value is identical. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please check the errors in the Travis build?
@dota17 I checked the errors on Travis and it seems the Could you please revert and remove the |
@nlohmann The commit has been modified according to your suggestion. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there was a misunderstanding. The PR now only adds a different encoding for NaN, +Inf, and -Inf. The patch from @rvjr also added an encoding to floats where possible. Can you re-add that - I only meant to remove the boolean parameter to switch on/off that encoding to floats as I think doing so is a good default.
Sorry for the confusion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that there are other CBOR tests failing.
@nlohmann These CBOR tests failed: |
I checked locally with some debug output:
The numbers 0.0, -0.0, 200, and 100 can be represented exactly by double and float. We just need to adjust the test cases. |
(see http://cbor.me for a helpful tool) |
Thank you for the detailed log info and the tool, that really helps. |
I didn't look into the testcase but just quickly checked what happens in the conversions with this tiny piece of code: void testConversion() {
std::vector<double> values = {0.0, -0.0, 0e+1, 0e1, 123.456e-789, 20e1, 1E+2, 1e+2, 123e-10000000};
for (int i = 0; i < (int)values.size(); i++) {
double v = values[i];
float vf = (float)v;
double vd = (double)vf;
printf(format("values[%d]==%f is a %s\n", i, v, vd == vf ? "float" : "double"));
}
} and this is the output: values[0]==0.000000 is a float So they are all stored as floats. I think everything is working fine; the point is just that 123.456e-789 and 123e-10000000 cannot be stored lossless in a double and have zero as closest representation in a 64 bit double value, so we can just as well store them as float zero (which is also correct in my opinion). |
clean commit and rebase. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me.
There is a warning from UBSAN which breaks the build, see https://travis-ci.org/github/nlohmann/json/jobs/686552145#L915:
|
Any ideas? |
Well this is exactly what this line is supposed to do: const float value_float = static_cast<float>(value_double); It should convert to float, as good as possible. And if there is no representation then we should detect this as not being representable as float, which is the intended use of the cast. |
I am confusing, in json_test_data, there is no such input data like |
I think the problem occurs when we handle a NaN or infinity value. We should first handle these cases and only then convert the value to float. That is, move the lines const auto value_double = j.m_value.number_float;
const float value_float = static_cast<float>(value_double); to the else branch. |
That still does not fix it. Did you try to run with UBSAN locally? Would be interesting to see which test fails. |
Just run it with UBSAN in local, the error still appeared: 7/49 Test #7: test-cbor ..........................***Failed 81.58 sec
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/bits/stl_bvector.h:158:20: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'unsigned int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/bits/stl_bvector.h:158:20 in
/data/jsonformodernc/llc/json/single_include/nlohmann/json.hpp:12146:64: runtime error: 1.79769e+308 is outside the range of representable values of type 'float'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /data/jsonformodernc/llc/json/single_include/nlohmann/json.hpp:12146:64 in |
You could run the test-cbor binary directly and check in the debugger in which line the error occurs. |
Well, it still at |
And which input? |
1e+300 |
Then I think we need to compare against |
Done, no more undefined-behavior in my local. |
Could you also test against min() and add some unit tests? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PS: When you always rebase/squash your commits, reviewing becomes very hard as I never see a delta from the last commit, but need to start fresh.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me.
Thanks! |
🔖 Release itemThis issue/PR will be part of the next release of the library. This template helps preparing the release notes. Type
Description
|
Pull request checklist
Read the Contribution Guidelines for detailed information.
include/nlohmann
directory, runmake amalgamate
to create the single-header filesingle_include/nlohmann/json.hpp
. The whole process is described here.Describe
As discussed in issue #1719, I made this PR base on @rvjr 's patch, and also refer to the author's suggestions in this comment