Skip to content
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

Improve the speed of parsing floating-point numbers #1496

Merged
merged 1 commit into from
Dec 8, 2021

Conversation

amyspark
Copy link
Contributor

@amyspark amyspark commented Sep 20, 2021

This MR brings in the amalgamated header of the fast_float library, and applies it to our uses of sscanf with %f. This library is locale-free, and does not incur the performance penalty of using a thread locale RAII class.

I have also included the relevant entries to THIRD_PARTY, and added a succint Readme listing the library version and its source, in the style of sampleicc.

Fixes #297
Fixes #379
Fixes #1322

@amyspark
Copy link
Contributor Author

Force-pushed again because of a typo in one of the issue numbers.

@remia
Copy link
Collaborator

remia commented Sep 21, 2021

Thanks for the contribution @amyspark, great to see some progress on this long standing issue ! I have yet to test that on actual files, though looking at the changes I already had questions (I have not followed all discussions on the topic over the years, trying to understand):

  • It looks like SPI[1|3]D format are the only users of sscanf to parse float numbers while other formats rely on StringToFloat from ParseUtils.h which rely on std::istringstream. Is that affected by the system locale as well ? I would assume we should use this helper everywhere and restrict usage of raw fast_float calls only there. Do we use sscanf on SPI formats due to specific performance requirements ?
  • Can we reproduce this locale issue in unit test and add in as part of the test suite ?

@amyspark
Copy link
Contributor Author

Hey @remia !

* It looks like SPI[1|3]D format are the only users of `sscanf` to parse float numbers while other formats rely on `StringToFloat` from `ParseUtils.h` which rely on `std::istringstream`. Is that affected by the system locale as well ? I would assume we should use this helper everywhere and restrict usage of raw fast_float calls only there.

Anything that is not std::atof is affected by the issue, starting with std::strtod up to any stringstream that uses floats. However, these could be worked around by imbuing the locale, but see below.

Do we use sscanf on SPI formats due to specific performance requirements ?

I believe so; iirc @hodoulp rejected the stringstream+imbuelocale approach because it is notoriously slower compared to a plain sscanf. And using C++17 from_chars wasn't an option because Clang to date still doesn't ship it.

* Can we reproduce this locale issue in unit test and add in as part of the test suite ?

It is tricky because you need to change the running thread's locale through your C runtime before being able to reproduce it, e.g. with LC_ALL or LANG set to any non-English locale that uses commas as thousands separator.

@amyspark
Copy link
Contributor Author

Since the parsing utils already pay the cost of stringstream, the last commit ensure they parse numbers according to the C locale.

@michdolan
Copy link
Collaborator

Thanks for your contribution @amyspark ! I added this PR to the TSC meeting agenda tomorrow for more discussion.

@hodoulp
Copy link
Member

hodoulp commented Oct 8, 2021

Use the ocioperf command line tool to measure the processor creation time (which is mainly loading the LUT file in that case).

Using the command ./src/apps/ocioperf/ocioperf --transform ./testdata/spi_ocio_srgb_test.spi3d --image ~/dev/images/aces/images/ACES/DigitalLAD.2048x1556.exr --iter 1 --nocache, the numbers are from ~ 28 ms to ~ 16 ms. It's almost two time faster for the 3D LUT read.

Using the command ./src/apps/ocioperf/ocioperf --transform ./testdata/lut1d_3.spi1d --image ~/dev/images/aces/images/ACES/DigitalLAD.2048x1556.exr --iter 1 --nocache, the numbers are from ~ 107 ms to ~116 ms. It means a slowdown of 10% for the 1D LUT read.

@hodoulp
Copy link
Member

hodoulp commented Oct 8, 2021

Following my first investigations, here are some thoughts:

  • There is a major performance improvement and some extra robustness added to the spi3d file format reader 🎉
  • There is a minor performance slowdown but some extra robustness added to the spi1d file format reader
    • The spi3d file format reader clearly demonstrates the right implementation which could be back-ported to the spi1d file format reader. 👀
  • As the clf file format is the long-term LUT file format (i.e. that's the ACES file format standard), changes should also be done in the clf file format reader
    • With extra care around the performance, the clf LUT reader requires the same kind of update. 👀

@hodoulp
Copy link
Member

hodoulp commented Oct 8, 2021

❗ As agreed at the last TSC meeting, all the third-party library dependencies must remain external (when used as-is) and be included using a dedicated FindXX() cmake method. You can check here for examples.

@amyspark
Copy link
Contributor Author

amyspark commented Oct 9, 2021

I was not present at the meeting, so I would like to take the opportunity to address these points below.

Michael: Says in PR it's amalgamated, but not certain if it's modified.

The library was fetched and committed as is from the release: https://github.com/fastfloat/fast_float/releases/tag/v3.1.0. https://github.com/fastfloat/fast_float/tree/v3.1.0#using-as-single-header lists the amalgamation process. I'm afraid the upstream doesn't list SHA256 hashes, so I cannot provide more assurances regarding that.

Kevin: Provides amalgamated file in GH project. Apache 2 license. Is this the right code to be adding? Is this the right solution to solving locale issue? I know every month there's something better or faster, and eventually some of this will make it into standard library. Is the core idea is to solve locale parsing/serializing problem? Is this library a reasonable solution for that?

The list of issues in this PR shows that this bug has existed for almost a decade, which is a very long time in our field.
It is correct, however, that the standard library now allows users to parse floating-point numbers locale-free, with the addition of std::from_chars. However, when one looks more in depth, this is not entirely true.

This feature in particular not only requires a fairly new standard (for instance, we at Krita only moved to 14 last year), it also needs a very recent compiler. According to cppreference, to date, only GCC 11 and MSVC 2017 support from_chars with floating point numbers. Clang just released version 13, see the LLVM site), yet this particular feature is still under review. See D70631 at the LLVM site. In all cases, we are limited to C++17 -- there is no chance to use from_chars with 14 or 11, which is what this library adds.

Kevin: Actual repo is header only. If we didn't want to include it, could use submodule to pull down or something.

Kevin: Would prefer it to be external dependency. As long as it doesn't break or regress, ok with this library. Should make sure it doesn't change a lot. Doesn't have a lot of commits.

I will port it to an external dependency in the next force push.

Rémi: stringstream is slow

stringstream is unavoidable until OpenColorIO migrates its formatting utilities to fmt, because from_chars doesn't cover float-to-string.

@amyspark amyspark force-pushed the amyspark/locale branch 2 times, most recently from e4ae2f5 to c4dddb7 Compare October 9, 2021 02:39
@amyspark
Copy link
Contributor Author

amyspark commented Oct 9, 2021

I've now pushed the requested fixes. @hodoulp, Spi1D now also uses from_chars through the changes I made to StringVecToFloatVec, can you run your measurements again?

@hodoulp
Copy link
Member

hodoulp commented Oct 9, 2021

@amyspark OpenColorIO default C++ standard is still C++11. We recently agreed to move to C++14 to stay close to the default C++ version supported by the ecosystem (refer to pull request #1508) but C++11 must still compile. So, there is no way to directly use std::from_chars for example. The project tries to be extremely conservative in order to support any kind of integration. @KevinJW only wanted to challenge the choice and we finally agreed on the proposed approach to this long pending issue.

On the other hand, we are also extremely careful when adding a mandatory third-party library and how to integrate it in the project to keep the build easy for any external contributors or integrators.

The last commits are fixing all of these points: 1) spi1d improvements ✅ and 2) find method for fast_float ✅. But I will do the review later, I first want to validate the improvements/results.

BTW During my tests around the performance aspect, I also double-checked for the precision which seems the same i.e. no loss. ✅ From the fast_float documentation:
[..] The resulting floating-point value is the closest floating-point values (using either float or double), using the "round to even" convention for values that would otherwise fall right in-between two values. That is, we provide exact parsing according to the IEEE standard.

On my previous comment, I forgot to mention the unit test aspect. Even if the performance improvement is great the locale is the primary change to validate using a unit test 👀
The code could use std::locale::global and std::setlocale for example.

@lgritz
Copy link
Collaborator

lgritz commented Oct 9, 2021

Indeed, to_chars is actually a C++17 feature, not even C++14.

@amyspark
Copy link
Contributor Author

amyspark commented Oct 9, 2021

@lgritz Yeah, however it is usable though GCC and Clang in C++14 and C++11 (although they will trigger a -Wc++17-extensions warning).

@lgritz
Copy link
Collaborator

lgritz commented Oct 9, 2021

@amyspark Certainly. Though you'd need to map out which versions of those compilers support it (all the way back to the oldest versions that support C++14? really?) and what about MSVS?

@amyspark
Copy link
Contributor Author

amyspark commented Oct 9, 2021

@lgritz MSVC is standards compliant, i.e. it only allows from_chars with /std:c++17 onwards.

@hodoulp
Copy link
Member

hodoulp commented Oct 12, 2021

I think we should avoid compiler flags to enable features from 'higher' C++ versions. That would require much more CI builds (i.e. to test all combinations of compilers, flags, etc.) and also increase the risk of problems on not officially support platforms, compilers, etc.

@hodoulp
Copy link
Member

hodoulp commented Oct 12, 2021

Here are my new numbers demonstrating a major improvement for spi1d 🎉

master first changes second changes
spi1d 1 107 ms 116 ms 55 ms
spi3d 2 28 ms 16 ms 16 ms
clf (1D LUT) 3 44 ms x 43 ms
clf (3D LUT) 4 27 ms x 26 ms

Footnotes

  1. ./src/apps/ocioperf/ocioperf --transform ./testdata/lut1d_3.spi1d --image ~/dev/images/aces/images/ACES/DigitalLAD.2048x1556.exr --iter 1 --nocache

  2. ./src/apps/ocioperf/ocioperf --transform ./testdata/spi_ocio_srgb_test.spi3d --image ~/dev/images/aces/images/ACES/DigitalLAD.2048x1556.exr --iter 1 --nocache

  3. ./src/apps/ocioperf/ocioperf --transform ./testdata/clf/lut1d_long.clf --image ~/dev/images/aces/images/ACES/DigitalLAD.2048x1556.exr --iter 1 --nocache

  4. ./src/apps/ocioperf/ocioperf --transform ./testdata/clf/aces_to_video_with_look.clf --image ~/dev/images/aces/images/ACES/DigitalLAD.2048x1556.exr --iter 1 --nocache

@hodoulp
Copy link
Member

hodoulp commented Oct 12, 2021

I checked the changes, and I have few comments:

  • For the spi1d file format, there is another improvement by removing the use of StringUtils::SplitByWhiteSpaces(StringUtils::Trim(lineBuffer));. In fact all the block of code from line 187 to 210 in src/OpenColorIO/fileformats/FileFormatSpi1D.cpp) could be replaced by sscanf & fast_float::from_chars like in spi3d.
  • For clf file format, the idea is to improve ParseNumber().

@amyspark
Copy link
Contributor Author

amyspark commented Oct 13, 2021

For the spi1d file format, there is another improvement by removing the use of StringUtils::SplitByWhiteSpaces(StringUtils::Trim(lineBuffer));. In fact all the block of code from line 187 to 210 in src/OpenColorIO/fileformats/FileFormatSpi1D.cpp) could be replaced by sscanf & fast_float::from_chars like in spi3d.

Fixed in the upcoming commits.

For clf file format, the idea is to improve ParseNumber().

Here I am running into three semantic issues with strtod:

val = strtod(startParse, &endParse);

(from cppreference)

2-4) Floating-point parsers: Expects the pattern identical to the one used by std::strtod in the default ("C") locale, except that

  • the plus sign is not recognized outside of the exponent (only the minus sign is permitted at the beginning)
    (snip)
  • leading whitespace is not ignored.

It seems the CLF format relies explicitly on the plus sign and on the ability of strtod to skip leading whitespace, which makes from_chars impossible to use directly. I can work around both, but the latter is so far unfixable:

const char str1[] = "inf, -infinity 1.0, -2.0 0x42 nan , -nan 5.0";

fast_float doesn't have support for hex numbers at all. I'm going to push a new commit showing how to work around it, and let you decide if the workaround is good enough for production purposes.

@hodoulp
Copy link
Member

hodoulp commented Oct 14, 2021

❗ Not supporting numbers like +1.2 (minus sign is supported) and the hexadecimal notation like 0x0A is a major concern because that's currently supported. I will bring that topic to TSC members & community.

The side-effect of this finding is the demonstration of the lake of unit tests around the spi1d and spi3d file formats.

@hodoulp
Copy link
Member

hodoulp commented Oct 15, 2021

Here are few improvements before having the final answer about the go vs. no go for the library in OpenColorIO:

  • Only the header only library version must be used (i.e. the current FindFastFloat() method downloads the library and not the header file).
  • For the '+' challenge, the patch below should fix the problem (which removes one potential blocker 👍). I did some partial tests using the pull request and it works.
*** fast_float.h	2021-10-14 16:50:10.000000000 -0400
--- fast_float2.h	2021-10-15 16:58:29.000000000 -0400
***************
*** 505,511 ****
    answer.valid = false;
    answer.too_many_digits = false;
    answer.negative = (*p == '-');
!   if (*p == '-') { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here
      ++p;
      if (p == pend) {
        return answer;
--- 505,511 ----
    answer.valid = false;
    answer.too_many_digits = false;
    answer.negative = (*p == '-');
!   if (*p == '-' || *p == '+') {
      ++p;
      if (p == pend) {
        return answer;
***************
*** 642,648 ****
    answer.decimal_point = 0;
    answer.truncated = false;
    answer.negative = (*p == '-');
!   if (*p == '-') { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here
      ++p;
    }
    // skip leading zeroes
--- 642,648 ----
    answer.decimal_point = 0;
    answer.truncated = false;
    answer.negative = (*p == '-');
!   if (*p == '-' || *p == '+') {
      ++p;
    }
    // skip leading zeroes
***************
*** 1696,1702 ****
    answer.valid = false;
    answer.too_many_digits = false;
    answer.negative = (*p == '-');
!   if (*p == '-') { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here
      ++p;
      if (p == pend) {
        return answer;
--- 1696,1702 ----
    answer.valid = false;
    answer.too_many_digits = false;
    answer.negative = (*p == '-');
!   if (*p == '-' || *p == '+') {
      ++p;
      if (p == pend) {
        return answer;
***************
*** 1833,1839 ****
    answer.decimal_point = 0;
    answer.truncated = false;
    answer.negative = (*p == '-');
!   if (*p == '-') { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here
      ++p;
    }
    // skip leading zeroes
--- 1833,1839 ----
    answer.decimal_point = 0;
    answer.truncated = false;
    answer.negative = (*p == '-');
!   if (*p == '-' || *p == '+') {
      ++p;
    }
    // skip leading zeroes
***************
*** 2310,2318 ****
    from_chars_result answer;
    answer.ptr = first;
    answer.ec = std::errc(); // be optimistic
!   bool minusSign = false;
!   if (*first == '-') { // assume first < last, so dereference without checks; C++17 20.19.3.(7.1) explicitly forbids '+' here
!       minusSign = true;
        ++first;
    }
    if (last - first >= 3) {
--- 2310,2317 ----
    from_chars_result answer;
    answer.ptr = first;
    answer.ec = std::errc(); // be optimistic
!   const bool minusSign = (*first == '-');
!   if (*first == '-' || *first == '+') { // assume first < last, so dereference without checks
        ++first;
    }
    if (last - first >= 3) {

@hodoulp
Copy link
Member

hodoulp commented Oct 15, 2021

The new numbers are:

master first changes second changes third changes
spi1d 1 107 ms 116 ms 55 ms 32 ms 🎉
spi3d 2 28 ms 16 ms 16 ms 16 ms
clf (1D LUT) 3 44 ms x 43 ms 47 ms ❗
clf (3D LUT) 4 27 ms x 26 ms 27 ms

Comment: The performance hit for the clf file format could be related to the std::string usage which should be banned from this specific code. The parseNumber() must only manipulate the pointers.

Footnotes

  1. ./src/apps/ocioperf/ocioperf --transform ./testdata/lut1d_3.spi1d --image ~/dev/images/aces/images/ACES/DigitalLAD.2048x1556.exr --iter 1 --nocache

  2. ./src/apps/ocioperf/ocioperf --transform ./testdata/spi_ocio_srgb_test.spi3d --image ~/dev/images/aces/images/ACES/DigitalLAD.2048x1556.exr --iter 1 --nocache

  3. ./src/apps/ocioperf/ocioperf --transform ./testdata/clf/lut1d_long.clf --image ~/dev/images/aces/images/ACES/DigitalLAD.2048x1556.exr --iter 1 --nocache

  4. ./src/apps/ocioperf/ocioperf --transform ./testdata/clf/aces_to_video_with_look.clf --image ~/dev/images/aces/images/ACES/DigitalLAD.2048x1556.exr --iter 1 --nocache

@amyspark
Copy link
Contributor Author

Only the header only library version must be used (i.e. the current FindFastFloat() method downloads the library and not the header file).

@hodoulp, I understood that the library was to be built from source, as is done with the rest of the dependencies?

@hodoulp
Copy link
Member

hodoulp commented Oct 15, 2021

Only the header only library version must be used (i.e. the current FindFastFloat() method downloads the library and not the header file).

@hodoulp, I understood that the library was to be built from source, as is done with the rest of the dependencies?

In general, the third-party libraries are built from sources. But this one offers a header only solution which will reduce compile time. So, we should take it.

@hodoulp
Copy link
Member

hodoulp commented Nov 11, 2021

(Though, as OCIO specify its builds manually, I'm not sure if a full matrix duplication would be acceptable.)

No. As we try to keep the build number under control (i.e. there is already lot of builds) It would be great to only add one or two new entries.

@amyspark amyspark force-pushed the amyspark/locale branch 2 times, most recently from e88bfc0 to e742c40 Compare November 11, 2021 18:27
Copy link
Member

@hodoulp hodoulp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Want to put some time investigating the last point: parsing difference between fast_float::from_chars and ::strtof_l in order to remove the temp string.

src/utils/NumberUtils.h Show resolved Hide resolved
src/OpenColorIO/fileformats/xmlutils/XMLReaderUtils.h Outdated Show resolved Hide resolved
share/cmake/modules/FindFastFloat.cmake Outdated Show resolved Hide resolved
share/cmake/utils/CompilerFlags.cmake Outdated Show resolved Hide resolved
tests/cpu/fileformats/xmlutils/XMLReaderUtils_tests.cpp Outdated Show resolved Hide resolved
Copy link
Collaborator

@remia remia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR looks great @amyspark, I made a few minor points that are mostly questions and not issues. Also wondering if we can add a simple test case with, say simulating a French locale system and checking the behaviour is as expected (though I'm not sure the exact scope this test should cover). Has this been discussed and sorted already?

src/OpenColorIO/ParseUtils.cpp Outdated Show resolved Hide resolved
src/OpenColorIO/fileformats/FileFormatSpi1D.cpp Outdated Show resolved Hide resolved
src/utils/NumberUtils.h Show resolved Hide resolved
@remia
Copy link
Collaborator

remia commented Nov 16, 2021

Note: I believe the additional checks showing up in the list are due to the renaming of the jobs in the CI workflow file. We need to update the required list in the repository settings. Or at least that would be my guess.

@hodoulp
Copy link
Member

hodoulp commented Nov 29, 2021

The pull request now seems ready but I would like to double-check the performance of this final version before approving. Great job @amyspark

@remia
Copy link
Collaborator

remia commented Nov 30, 2021

As discussed yesterday here is some performance numbers (from different hardware) on the 3 major platforms using the new ocioperf tool as it exists on main (no longer need an image as input). While probably not strictly needed, I ran each commands twice and kept the second result only, trying to discard system cache.

macOS 11.6 AppleClang 13.0 CXX14

master (no locale fix) fast_float no fast_float
spi1d 1 126.306 37.7097 36.4144
spi3d 2 29.0348 18.3221 20.9059
clf (1D LUT) 3 44.6314 46.5028 47.2037
clf (3D LUT) 4 27.537 26.2199 29.2086

Windows 10 MSVC 19.16.27045.0 CXX14

master (no locale fix) fast_float no fast_float
spi1d 1 315.49 65.8565 89.2596
spi3d 2 30.5407 20.152 30.1545
clf (1D LUT) 3 71.519 54.939 71.3029
clf (3D LUT) 4 33.8682 25.1431 35.5455

Linux CentOS 7.6 GCC 9.3.1 CXX14

master (no locale fix) fast_float no fast_float
spi1d 1 444.353 100.728 145.077
spi3d 2 65.8942 50.4903 74.5444
clf (1D LUT) 3 126.986 89.4428 129.521
clf (3D LUT) 4 72.9861 48.4598 76.121

Footnotes

  1. ocioperf --transform ./testdata/lut1d_3.spi1d --iter 10 --nocache 2 3

  2. ocioperf --transform ./testdata/spi_ocio_srgb_test.spi3d --iter 10 --nocache 2 3

  3. ocioperf --transform ./testdata/clf/lut1d_long.clf --iter 10 --nocache 2 3

  4. ocioperf --transform ./testdata/clf/aces_to_video_with_look.clf --iter 10 --nocache 2 3

@hodoulp
Copy link
Member

hodoulp commented Dec 6, 2021

@amyspark The add of a library dependency in the 'core' library is always a challenging discussion because of all the potential impacts on short and long term for OpenColorIO maintainers but also for package managers, external contributors, etc. In that case, the goal is to add these changes to the coming 2.1.1 release so, we cannot add a new dependency. The patch version 2.1.1 is planned for next week, will you have the time to cleanup the code?

@amyspark
Copy link
Contributor Author

amyspark commented Dec 6, 2021

@hodoulp What would be, more precisely, the changes you'd like in this MR? And what should be moved to another commit or MR?

@hodoulp
Copy link
Member

hodoulp commented Dec 6, 2021

Please remove the fast_float dependency i.e. the code must only use the 'custom' implementation.

Copy link
Member

@hodoulp hodoulp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job

Copy link
Collaborator

@doug-walker doug-walker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this work amyspark and for your patience during the long process of finding a solution that meets the many requirements/constraints!

Copy link
Collaborator

@remia remia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the work @amyspark! Just a minor point for coherence about the sscanf on Windows but all good to merge for me as well regardless.

src/OpenColorIO/fileformats/FileFormatSpi1D.cpp Outdated Show resolved Hide resolved
This commit adds support for parsing numbers without being influenced by
the current system locale. We implement a from_chars
shim that forwards the call to strto*_l along with a statically
initialized locale constant.

Fixes AcademySoftwareFoundation#297
Fixes AcademySoftwareFoundation#379
Fixes AcademySoftwareFoundation#1322

Co-Authored-By: Patrick Hodoul <Patrick.Hodoul@autodesk.com>

Signed-off-by: L. E. Segovia <13498015+amyspark@users.noreply.github.com>
@hodoulp hodoulp merged commit b2f927b into AcademySoftwareFoundation:main Dec 8, 2021
hodoulp pushed a commit that referenced this pull request Dec 8, 2021
This commit adds support for parsing numbers without being influenced by
the current system locale. We implement a from_chars
shim that forwards the call to strto*_l along with a statically
initialized locale constant.

Fixes #297
Fixes #379
Fixes #1322

Co-Authored-By: Patrick Hodoul <Patrick.Hodoul@autodesk.com>

Signed-off-by: L. E. Segovia <13498015+amyspark@users.noreply.github.com>
hodoulp pushed a commit that referenced this pull request Dec 9, 2021
This commit adds support for parsing numbers without being influenced by
the current system locale. We implement a from_chars
shim that forwards the call to strto*_l along with a statically
initialized locale constant.

Fixes #297
Fixes #379
Fixes #1322

Co-Authored-By: Patrick Hodoul <Patrick.Hodoul@autodesk.com>

Signed-off-by: amyspark <13498015+amyspark@users.noreply.github.com>
hodoulp added a commit that referenced this pull request Dec 9, 2021
This commit adds support for parsing numbers without being influenced by
the current system locale. We implement a from_chars
shim that forwards the call to strto*_l along with a statically
initialized locale constant.

Fixes #297
Fixes #379
Fixes #1322

Co-Authored-By: Patrick Hodoul <Patrick.Hodoul@autodesk.com>

Signed-off-by: amyspark <13498015+amyspark@users.noreply.github.com>

Co-authored-by: amyspark <13498015+amyspark@users.noreply.github.com>
@amyspark amyspark deleted the amyspark/locale branch December 13, 2021 11:10
@doug-walker doug-walker changed the title Use the fast_float library to parse floating-point numbers Improve the speed of parsing floating-point numbers Oct 31, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
7 participants