Skip to content

Commit e22c027

Browse files
author
allen.barnett@paperbirchsoftware.com
committed
Allow fast_float to parse strings accepted by the Fortran internal read
function.
1 parent 6a390f6 commit e22c027

File tree

4 files changed

+69
-3
lines changed

4 files changed

+69
-3
lines changed

include/fast_float/ascii_number.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,9 +328,17 @@ parsed_number_string_t<UC> parse_number_string(UC const *p, UC const * pend, par
328328
return answer;
329329
}
330330
int64_t exp_number = 0; // explicit exponential part
331-
if ((fmt & chars_format::scientific) && (p != pend) && ((UC('e') == *p) || (UC('E') == *p))) {
331+
if ( ((fmt & chars_format::scientific) &&
332+
(p != pend) &&
333+
((UC('e') == *p) || (UC('E') == *p)))
334+
||
335+
((fmt & chars_format::fortran) &&
336+
(p != pend) &&
337+
((UC('+') == *p) || (UC('-') == *p) || (UC('d') == *p) || (UC('D') == *p)))) {
332338
UC const * location_of_e = p;
333-
++p;
339+
if ((UC('e') == *p) || (UC('E') == *p) || (UC('d') == *p) || (UC('D') == *p)) {
340+
++p;
341+
}
334342
bool neg_exp = false;
335343
if ((p != pend) && (UC('-') == *p)) {
336344
neg_exp = true;

include/fast_float/float_common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ enum chars_format {
1616
scientific = 1 << 0,
1717
fixed = 1 << 2,
1818
hex = 1 << 3,
19+
fortran = 1 << 4 | fixed | scientific,
1920
general = fixed | scientific
2021
};
2122

tests/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ fast_float_add_cpp_test(long_test)
7272
fast_float_add_cpp_test(powersoffive_hardround)
7373
fast_float_add_cpp_test(string_test)
7474

75-
75+
fast_float_add_cpp_test(fortran)
7676

7777
option(FASTFLOAT_EXHAUSTIVE "Exhaustive tests" OFF)
7878

tests/fortran.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Exercise the Fortran conversion option.
3+
*/
4+
#include <cstdlib>
5+
#include <iostream>
6+
#include <vector>
7+
8+
#define FASTFLOAT_ALLOWS_LEADING_PLUS
9+
10+
#include "fast_float/fast_float.h"
11+
12+
int main ()
13+
{
14+
const std::vector<double> expected{ 10000, 1000, 100, 10, 1, .1, .01, .001, .0001 };
15+
const std::vector<std::string> fmt1{ "1+4", "1+3", "1+2", "1+1", "1+0", "1-1", "1-2",
16+
"1-3", "1-4" };
17+
const std::vector<std::string> fmt2{ "1d+4", "1d+3", "1d+2", "1d+1", "1d+0", "1d-1",
18+
"1d-2", "1d-3", "1d-4" };
19+
const std::vector<std::string> fmt3{ "+1+4", "+1+3", "+1+2", "+1+1", "+1+0", "+1-1",
20+
"+1-2", "+1-3", "+1-4" };
21+
const fast_float::parse_options options{ fast_float::chars_format::fortran };
22+
23+
for ( auto const& f : fmt1 ) {
24+
auto d{ std::distance( &fmt1[0], &f ) };
25+
double result;
26+
auto answer{ fast_float::from_chars_advanced( f.data(), f.data()+f.size(), result,
27+
options ) };
28+
if ( answer.ec != std::errc() || result != expected[std::size_t(d)] ) {
29+
std::cerr << "parsing failure on " << f << std::endl;
30+
return EXIT_FAILURE;
31+
}
32+
}
33+
34+
for ( auto const& f : fmt2 ) {
35+
auto d{ std::distance( &fmt2[0], &f ) };
36+
double result;
37+
auto answer{ fast_float::from_chars_advanced( f.data(), f.data()+f.size(), result,
38+
options ) };
39+
if ( answer.ec != std::errc() || result != expected[std::size_t(d)] ) {
40+
std::cerr << "parsing failure on " << f << std::endl;
41+
return EXIT_FAILURE;
42+
}
43+
}
44+
45+
for ( auto const& f : fmt3 ) {
46+
auto d{ std::distance( &fmt3[0], &f ) };
47+
double result;
48+
auto answer{ fast_float::from_chars_advanced( f.data(), f.data()+f.size(), result,
49+
options ) };
50+
if ( answer.ec != std::errc() || result != expected[std::size_t(d)] ) {
51+
std::cerr << "parsing failure on " << f << std::endl;
52+
return EXIT_FAILURE;
53+
}
54+
}
55+
56+
return EXIT_SUCCESS;
57+
}

0 commit comments

Comments
 (0)